题目链接

题意

有 \(n\) 个容积无限的水缸,初始时水量为\(a_1,a_2,...,a_n\),有一把容积为\(k\)的勺子,可以从一个水缸中舀水倒入另一个水缸中。问能否给出操作序列,使得最终某一个水缸中水的容量为\(V\).

思路

参考 - 粉兔.

结论

首先,如果\(\sum_{i=1}^{n}a_i\lt V\),显然不可行。

否则,一旦\(\exists p_1,p_2,...,p_t,s.t.(\sum_{i=1}^{t}a_{p_i})\%k==V\%k\),则我们说,这件事是可行的。

为什么呢?因为一旦可以取到同余的值,那么无论总量是多余还是不足都可以用勺子解决:多了,就往外舀;少了,就从其他缸(\(i.e.\) 第\(j\)个\((j!=p_i(i=1,2,...,t)\)))中补进来。

至于操作的具体细节,暂放一下。

dp

那么该怎么判断是否有上面的条件成立呢?

用 \(dp[i][j]\) 表示前 \(i\) 个缸能否取到模数为 \(j\) 的值,特别的,

\[dp[i][j]=\begin{cases}0,&cannot\ make\ it\cr1,&can\ make\ it\ without\ a_i\cr2,&a_i\ needed\ to\ make\ it\cr\end{cases}
\]

则 \(dp[n][V\%k]\) 即表示前 \(n\) 个缸能否取到模数为 \(k\) 的值。

构造

现在有了这个结论和中间记录的 \(dp\) 值,该怎么推出步骤呢?

注意到,上面的记录过程提供给了我们 \(p_1,p_2,...,p_t\),即必须全部取的缸;而其余的缸,不妨记为 \(q_1,q_2,...,q_s\)。

则可行操作如下:

  1. 将 \(p1,...,p_{t-1}\) 缸中的水全部舀入 \(p_t\) 中;
  2. 将 \(q1,...,q_{s-1}\) 缸中的水全部舀入 \(q_s\) 中;
  3. 在 \(p_t\) 与 \(q_s\) 之间进行多退少补。

注意几种 特殊情况,比如 \(t=n\) 和 \(s=n\) 的情况:

\(t=n\) 即所有的缸都需要,最后总量肯定只会超出,不会不够,并且超出的部分必然是 \(k\) 的整倍数。

此时,将所有缸中的水都舀到某一个缸中,再将超出的部分舀到另一个缸中;

(这种情况可以与一般情况合在一起统一处理)。

\(s=n\) 即所有的缸都不需要,这是什么回事呢?当 \(k|V\) 时就会发生这种情况,即所需要的容积恰好可以用若干勺舀出。

此时,将所有缸中的水都舀到某一个缸中,再将需要的部分舀到另一个缸中。

// 很佩服粉兔啦%%%

Code

  1. #include <bits/stdc++.h>
  2. #define maxn 5010
  3. using namespace std;
  4. typedef long long LL;
  5. int a[maxn], b[maxn], dp[maxn][maxn];
  6. bool flag[maxn];
  7. int main() {
  8. int n, k, v, sum = 0;
  9. scanf("%d%d%d", &n, &k, &v);
  10. for (int i = 1; i <= n; ++i) {
  11. scanf("%d", &a[i]);
  12. sum += (b[i] = a[i]), a[i] %= k;
  13. }
  14. if (sum < v) { puts("NO"); return 0; }
  15. dp[0][0] = 1;
  16. for (int i = 1; i <= n; ++i) {
  17. for (int j = 0; j < k; ++j) {
  18. if (dp[i-1][j]) {
  19. dp[i][j] = 1;
  20. if (!dp[i][(j+a[i])%k]) dp[i][(j+a[i])%k] = 2;
  21. }
  22. }
  23. }
  24. int tar = v % k;
  25. if (!dp[n][tar]) { puts("NO"); return 0; }
  26. puts("YES");
  27. int ans = 0, fnl1 = -1, fnl2 = -1;
  28. for (int i = n; i >= 1; --i) {
  29. if (dp[i][tar]==2) {
  30. flag[i] = true, (tar += k-a[i]) %= k, ans += b[i];
  31. if (fnl1==-1) fnl1 = i;
  32. }
  33. else if (fnl2 == -1) fnl2 = i;
  34. }
  35. if (fnl1==-1) {
  36. for (int i = 1; i < n; ++i) if (b[i]) {
  37. printf("%d %d %d\n", (b[i] + k-1)/k, i, n);
  38. }
  39. if (v/k) printf("%d %d %d\n", v/k, n, 1);
  40. return 0;
  41. }
  42. assert((v-ans) % k == 0);
  43. int rem = v - ans;
  44. int S1 = b[fnl1], S2 = b[fnl2];
  45. for (int i = 1; i <= n; ++i) {
  46. if (i == fnl1 || i == fnl2 || !b[i]) continue;
  47. if (!flag[i]) printf("%d %d %d\n", (b[i]+k-1)/k, i, fnl2), S2 += b[i];
  48. else printf("%d %d %d\n", (b[i]+k-1)/k, i, fnl1), S1 += b[i];
  49. }
  50. assert((v-S1) % k == 0);
  51. int cnt = (v-S1) / k;
  52. if (cnt>0) printf("%d %d %d\n", cnt, fnl2, fnl1);
  53. else if (cnt<0) printf("%d %d %d\n", -cnt, fnl1, 1);
  54. return 0;
  55. }

Codeforces 920D Tanks的更多相关文章

  1. Codeforces Educational Round 37

    Solved   CodeForces 920A Water The Garden   Solved   CodeForces 920B Tea Queue   Solved   CodeForces ...

  2. Codeforces Round #115 B. Plane of Tanks: Pro 水题

    B. Plane of Tanks: Pro Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/17 ...

  3. Codeforces 877 C. Slava and tanks

    http://codeforces.com/problemset/problem/877/C   C. Slava and tanks time limit per test 2 seconds me ...

  4. codeforces 414D Mashmokh and Water Tanks

    codeforces 414D Mashmokh and Water Tanks 题意 题解 \(a_i\):第 \(i\) 层的结点个数. \(b_i\):第 \(i\) 层初始有水的结点个数. 如 ...

  5. 【codeforces 175D】 Plane of Tanks: Duel

    http://codeforces.com/problemset/problem/175/D (题目链接) 题意 A,B两人玩坦克大战,坦克有生命值,射击间隔,伤害范围,未命中的概率.问A赢的概率是多 ...

  6. Codeforces 877C Slava and tanks(思维)

    题目链接:http://codeforces.com/problemset 题目大意:有n个格子,某些格子里可能有一个或多个坦克,但不知道具体位置,每个坦克被轰炸一次就会移动到相邻的格子里(第1个格子 ...

  7. 【Codeforces Round #442 (Div. 2) C】Slava and tanks

    [链接] 我是链接,点我呀:) [题意] 有n个位置,每个位置都可能有不定数量的tank; 你每次可以选择一个位置投掷炸弹. 并且,这个位置上的所有tank都会受到你的攻击. 并且失去一点体力. 然后 ...

  8. Codeforces Round #339 (Div. 2) B. Gena's Code 水题

    B. Gena's Code 题目连接: http://www.codeforces.com/contest/614/problem/B Description It's the year 4527 ...

  9. Educational Codeforces Round 37

    Educational Codeforces Round 37 这场有点炸,题目比较水,但只做了3题QAQ.还是实力不够啊! 写下题解算了--(写的比较粗糙,细节或者bug可以私聊2333) A. W ...

随机推荐

  1. k8s的认证和service account简述

    k8s的认证: 与API server通信的客户端大致有两类:  1.集群客户端工具(kubectl.kubeadm.kubelet等)  2.集群内pod. 任何客户端访问k8s时的过程:  1.认 ...

  2. 使用eclipse导入web项目

    第一步 第二步 第三步 第四步 最后就多了一个web项目

  3. BFS:Nightmare(可返回路径)

    解题心得: 1.point:关于可以返回路径的BFS的标记方法,并非是简单的0-1,而是可以用时间比较之后判断是否push. 2.queue创建的地点(初始化问题),在全局中创建queue在一次调用B ...

  4. Android设为系统默认的短信应用

    要设为系统默认的短信应用首先要配置一下AndroidManifest.xml文件,添加下列: <!-- BroadcastReceiver that listens for incoming S ...

  5. WPF异步回调时回调函数如何获取异步函数产生的变量

    有这么一个问题,WPF在使用异步回调的时候,回调函数需要用到异步函数里产生的一个变量,例如异步函数里查询数据库得到了一个DataTable,如何传递给回调函数呢? [方案一]使用全局变量 很容易想到的 ...

  6. cf976f Minimal k-covering

    枚举 \(k\),对于每个点 \(i\) 我们最多删 \(deg_i-k\) 条边,就源点向第一部.第二部向汇点连边,容量是 \(deg_i-k\),原边连上,容量是 \(1\),这样每流过一条原边在 ...

  7. 虚拟架构就绪 | 谈谈Windows Server 2012 R2迁移这件小事

    我们所说的“新选择”包括操作系统升级——告别Windows Server 2003或2008,选择用什么样的姿势进行升级呢? 新年伊始,正是企业对自身IT基础设施进行评估的最佳时期.在多项评估项目里面 ...

  8. IOS开发学习笔记022-imageView实现动画

    这里要播放的动画是很多张连续的动画,连续播放就会显示出动画效果. 大概过程是: 新建一个single view application ,然后添加一个image View控件到视图.给image vi ...

  9. CSU-1163 寒衣调

    CSU-1163 寒衣调 Description 男从戎,女守家.一夜,狼烟四起,男战死沙场.从此一道黄泉,两地离别.最后,女终于在等待中老去逝去.逝去的最后是换尽一生等到的相逢和团圆. 某日两人至奈 ...

  10. (转载)django 访问url报错Forbidden (CSRF cookie not set.): xxx 问

    原地址:http://www.cnblogs.com/meitian/p/7016336.html 问题:页面访问时报错 Forbidden (CSRF cookie not set.): xxx   ...