1058 Min酱要旅行 01背包变式 递推求方案数
链接:https://ac.nowcoder.com/acm/problem/210520
来源:牛客网
题目描述
从前有个富帅叫做Min酱,他很喜欢出门旅行,每次出门旅行,他会准备很大一个包裹以及一大堆东西,然后尝试各种方案去塞满它。
然而每次出门前,Min酱都会有个小小的烦恼。众所周知,富帅是很讨妹子喜欢的,所以Min酱也是有大把大把的妹子,每次出门都会有一只妹子随行。然而这些妹子总是会非常排斥Min酱准备的众多东西中的一件(也许是因为这件东西是其它妹子送给Min酱的),这件东西Min酱是万万不敢带上的,否则的话……嘿嘿嘿。另外,妹子们嫌Min酱的包裹太丑了,会自带一个包裹去换掉Min酱的包裹。
Min酱是个控制欲很强的人,然而这样一来,Min酱就不知道可以用多少种方案去填充包裹了,所以Min酱很郁闷。
于是Min酱找到了聪明的你,希望你能帮助他解决这些问题。
另外,Min酱是个典型的懒人,他不希望每次带不同的妹子出去都麻烦你,所以他希望你能给出有K1..KnK_1..K_nK1..Kn 件物品,第 i\ i i 件不能带并且包裹大小为 1..M\ 1..M 1..M 的所有方案数。
然而每次出门前,Min酱都会有个小小的烦恼。众所周知,富帅是很讨妹子喜欢的,所以Min酱也是有大把大把的妹子,每次出门都会有一只妹子随行。然而这些妹子总是会非常排斥Min酱准备的众多东西中的一件(也许是因为这件东西是其它妹子送给Min酱的),这件东西Min酱是万万不敢带上的,否则的话……嘿嘿嘿。另外,妹子们嫌Min酱的包裹太丑了,会自带一个包裹去换掉Min酱的包裹。
Min酱是个控制欲很强的人,然而这样一来,Min酱就不知道可以用多少种方案去填充包裹了,所以Min酱很郁闷。
于是Min酱找到了聪明的你,希望你能帮助他解决这些问题。
另外,Min酱是个典型的懒人,他不希望每次带不同的妹子出去都麻烦你,所以他希望你能给出有K1..KnK_1..K_nK1..Kn 件物品,第 i\ i i 件不能带并且包裹大小为 1..M\ 1..M 1..M 的所有方案数。
输入描述:
可能有多组数据。对于每一组数据:
第一行,两个整数 n,m\ n,m n,m,分别表示物品数量和妹子带的包裹的最大容积。
第二行, n\ n n 个正整数,分别表示物品 KiK_iKi 的体积。
输出描述:
对于每一组数据,输出一个 n×mn \times mn×m 的矩阵,第 i\ i i 行 j\ j j 列表示包裹容积为 j\ j j ,不能带 i\ i i 号物品时,装满包裹的方案总数。
为了美观起见,我们只保留方案数的个位。
备注:
1≤n,m≤2300,Ki≤10001\leq n,m \leq 2300,K_i \leq 10001≤n,m≤2300,Ki≤1000
分析
递推求方案数的问题,问不选择某个数在某个体积的时候的方案数。
按照一般的思路,先把所有的方案数求出来 再减去 选择某个数的时候的方案数 就是答案
如何求出选择某个物品的方案数呢?
由01背包压缩体积后的方程可知,dp[j] 表示的是选择体积j 时候的方案数
那么当 j < a[i] 的时候。dp[j] 表示的就是不选择 a[i] 的时候的方案数
设 g[j] 表示不选择 i 的体积为j 的时候的方案数,有状态转移方程式
g[j] = dp[j] (j < a[i])
g[j] = dp[j] - g[j - a[i]];
//-------------------------代码---------------------------- //#define int ll const int N = 1e5+10; int n,m; int a[N]; int f[N],g[N]; void solve() { ms(f,0); cin>>n>>m; fo(i,1,n) cin>>a[i]; f[0] = 1; fo(i,1,n) { of(j,m,a[i]) { f[j]=(f[j]+f[j-a[i]])%10; } } fo(i,1,n) { fo(j,0,m) { if(j<a[i])g[j] = f[j]; else g[j] =(( f[j] - g[j-a[i]]) + 10 ) % 10; } fo(j,1,m) { cout<<g[j]; }cout<<endl; } } signed main(){ clapping();TLE; // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------