【BZOJ2287】消失之物 [分治][DP]
消失之物
Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss]
Description
ftiasch 有 N 个物品, 体积分别是 W1, W2, ..., WN。
由于她的疏忽, 第 i 个物品丢失了.
“要使用剩下的 N - 1 物品装满容积为 x 的背包,有几种方法呢?” -- 这是经典的问题了。
她把答案记为 Count(i, x) ,想要得到所有1 <= i <= N, 1 <= x <= M的 Count(i, x) 表格。
Input
第1行:两个整数 N 和 M ,物品的数量和最大的容积。
第2行: N 个整数 W1, W2, ..., WN, 物品的体积。
Output
一个 N × M 的矩阵, Count(i, x)的末位数字。
Sample Input
3 2
1 1 2
1 1 2
Sample Output
11
11
21
11
21
HINT
1 ≤ N ≤ 2 × 1e3, 1 ≤ M ≤ 2 × 1e3
Solution
首先,我们发现,对于L,R:
去掉L,就是要用[1, L - 1]∪[L + 1, n]的物品来求解;
去掉R,就是要用[1, R - 1]∪[R + 1, n]的物品来求解。
若是我们更新完了([1, L - 1]∪[L + 1, n])∩([1, R - 1]∪[R + 1, n])的部分,
再加上L的,即是去掉R的答案;再加上R的,即是去掉L的答案。
那么我们就可以考虑分治:
设计状态Solve(L, R),表示已经做完了[1, L - 1]∪[R + 1, n]时的答案。
然后二分一个mid = L + R >> 1;
要处理[L, mid]则将[mid + 1, R]的更新一下,反之同理。
那么这样我们最后做到L == R时候,显然就是去掉L的答案了。
DP部分显然就是一个简单的背包。
Code
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 #include<queue> 9 using namespace std; 10 typedef long long s64; 11 12 const int ONE = 100005; 13 const int INF = 2147483640; 14 15 int n, m; 16 int a[ONE]; 17 int f[20][ONE]; 18 19 int get() 20 { 21 int res=1,Q=1; char c; 22 while( (c=getchar())<48 || c>57) 23 if(c=='-')Q=-1; 24 if(Q) res=c-48; 25 while((c=getchar())>=48 && c<=57) 26 res=res*10+c-48; 27 return res*Q; 28 } 29 30 void Solve(int L, int R, int Dep) 31 { 32 if(L == R) 33 { 34 for(int j = 1; j <= m; j++) 35 printf("%d", f[Dep][j]); 36 printf("\n"); 37 return; 38 } 39 40 int mid = L + R >> 1; 41 42 for(int j = m; j >= 0; j--) f[Dep + 1][j] = f[Dep][j]; 43 for(int i = mid + 1; i <= R; i++) 44 for(int j = m; j >= 0; j--) 45 (f[Dep + 1][j] += f[Dep + 1][j - a[i]]) %= 10; 46 Solve(L, mid, Dep + 1); 47 48 for(int j = m; j >= 0; j--) f[Dep + 1][j] = f[Dep][j]; 49 for(int i = L; i <= mid; i++) 50 for(int j = m; j >= 0; j--) 51 (f[Dep + 1][j] += f[Dep + 1][j - a[i]]) %= 10; 52 Solve(mid + 1, R, Dep + 1); 53 } 54 55 int main() 56 { 57 n = get(); m = get(); 58 for(int i = 1; i <= n; i++) a[i] = get(); 59 f[0][0] = 1; 60 Solve(1, n, 0); 61 }