HDU 1114 Piggy-Bank 完全背包问题、
想想我们01背包是逆序遍历是为了保证什么?
保证每件物品只有两种状态,取或者不取.那么正序遍历呢? 这不就正好满足完全背包的条件了吗
means:给出小猪钱罐的重量和装满钱后的重量,然后是几组数据,每组数据包括每种钱币的价值与重量要求出装满钱罐时的最小价值
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 using namespace std; 6 const int qq=50000+10; 7 const int MAX=1e8; 8 int dp[qq]; 9 int v[qq],p[qq]; 10 int main() 11 { 12 int t;scanf("%d",&t); 13 while(t--){ 14 int a,b;scanf("%d%d",&a,&b); 15 int c=b-a; 16 int n;scanf("%d",&n); 17 for(int i=0;i<n;++i) 18 scanf("%d%d",&p[i],&v[i]); 19 for(int i=1;i<=c;++i) 20 dp[i]=MAX; 21 dp[0]=0; 22 for(int i=0;i<n;++i) 23 for(int j=v[i];j<=c;++j) 24 dp[j]=min(dp[j],dp[j-v[i]]+p[i]); 25 if(dp[c]==MAX) printf("This is impossible. "); 26 else printf("The minimum amount of money in the piggy-bank is %d. ",dp[c]); 27 } 28 return 0; 29 }
HDU 2191 多重背包问题、
其实还是应用01背包的思想、不过这里有一个小技巧就是二进制表示法、
比如 13、可以表示成 1+2+4+5 这4个数可以组成1到13之间的任意一个数、
那么就可以多重背包拆分成01背包问题、
千万注意将空间压缩成一维的话是逆序遍历、这里解释一下 dp数组中的每一个值都是一种状态,该种状态在当前是独立的不受其他影响的,如果正序遍历的话前面得到的一些状态影响其他状态的生成、
- -、我是这么理解的、 总之你要dp的话就是... 唉本弱弱语文水平好差、
联想一下二维数组下是怎么更新状态的、再看看一维、这样就很容易理解了
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 const int qq=1000; 7 int p[qq],v[qq]; 8 int dp[qq]; 9 int main() 10 { 11 int t;scanf("%d",&t); 12 while(t--){ 13 int price,kind; 14 scanf("%d%d",&price,&kind); 15 int count=0; 16 int a,b,c; 17 for(int i=0;i<kind;++i){ 18 scanf("%d%d%d",&a,&b,&c); 19 int t=1; 20 while(c>=t){ 21 p[count]=a*t; 22 v[count++]=b*t; 23 c=c-t; 24 t=t<<1; 25 } 26 if(c){ 27 p[count]=a*c; 28 v[count++]=b*c; 29 } 30 } 31 for(int j,i=0;i<count;++i) 32 for(j=price;j>=p[i];--j) 33 dp[j]=max(dp[j],dp[j-p[i]]+v[i]); 34 printf("%d ",dp[price]); 35 memset(dp,0,sizeof(dp)); //一定记得初始化、毕竟有很多组数据、 36 } 37 return 0; 38 }