P4141 消失之物

-------------------------------------------

链接:P4141 消失之物

--------------------------------------------------

这道题确实很坑,在上课的时候,我们老师讲了一个分治的做法。

然而分治实在太玄学了。但是老师的课件上面还写了“有一种更简单的操作,但是没有拓展性。”

这种做法是什么呢?

非常简单,比如说我们要求出在没有i物品时的x的方案,我们只要先跑一边背包得到在所有物品都有的情况下的方案总数,然后把由i物品得到的方案数(贡献)减掉就行了

很简单吧(所以说没拓展性)

--------------------------------------------------

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int f[10000];//第一遍背包的数组 
 7 int n;
 8 int v[10000];
 9 int g[10000];//因为我们会经常更新,
10 //所以需要一个额外数组 
11 int m;
12 
13 int main(){
14     cin>>n>>m;
15     for(int i=1;i<=n;++i){
16         cin>>v[i];
17     }
18     g[0]=f[0]=1;
19     for(int i=1;i<=n;++i)
20         for(int j=m;j>=0;--j){
21             if(j>=v[i])
22             {
23                 f[j]+=f[j-v[i]];
24                 f[j]%=10;
25             }
26         }
27         
28     //标准的01背包求方案数 
29     for(int i=1;i<=n;++i)//枚举失去每一个物品 
30     {
31         memcpy(g,f,sizeof(f));//一定不能操作原数组 
32         for(int j=1;j<=m;++j){//枚举失去后的每一种可能的要求容量 
33             if(j>=v[i]){
34                 g[j]-=g[j-v[i]];//减去由i得到的部分 
35                 g[j]+=10;//有可能是负数 
36                 g[j]%=10;
37             }
38             else
39             g[j]=f[j]%10;
40             cout<<g[j];
41         }
42         cout<<endl;
43     }
44     return 0;
45 }
Ac

 

posted @ 2019-07-25 20:06  Simex  阅读(206)  评论(0编辑  收藏  举报