UVa 624 CD (01背包路径输出)
2013-07-15 10:12
375 查看
好久前做的题了,今天总结写这篇博文的时候UVA正好挂了……
题意:要把cd上的音乐导到磁带里,要求尽量使磁带剩余的空间小并按输入顺序顺序打印出每次磁带中的每个音轨长度。
思路:因为不久前学过状态压缩,所以马上想到用01记录状态。总数不超过20个,用int数记录状态,对每一位:0表示不取,1表示取。
最开始我的写法是这样的(pre是二维数组):
然后优化到一维:
下面贴一份比赛中共享的一份代码,用另一种思路做的:
在贴一份网上的解法,和我最开始的思路一样,不过当时我没有实现出来……
http://www.cppblog.com/syhd142/articles/118968.html
题意:要把cd上的音乐导到磁带里,要求尽量使磁带剩余的空间小并按输入顺序顺序打印出每次磁带中的每个音轨长度。
思路:因为不久前学过状态压缩,所以马上想到用01记录状态。总数不超过20个,用int数记录状态,对每一位:0表示不取,1表示取。
#include <cstdio> #include <cstring> #define max(a,b) ((a)>(b)?(a):(b)) int data[25],v,n; int dp[10005]; int pre[10005]; void Output (int str) { for (int i=1;i<=n;i++) if ((str>>i)&1) printf("%d ",data[i]); } int main () { while (~scanf("%d %d",&v,&n)) { int i; memset(dp,0,sizeof(dp)); memset(pre,0,sizeof(pre)); for (i=1;i<=n;i++) scanf("%d",&data[i]); for (i=1;i<=n;i++) for (int j=v;j>=data[i];j--) ///////// if (dp[j]<dp[j-data[i]]+data[i]) { dp[j]=dp[j-data[i]]+data[i]; pre[j]=pre[j-data[i]]|(1<<i); } Output (pre[v]); printf("sum:%d\n",dp[v]); } return 0; }注释部分之后的内容是优化过的,思路和导出01背包一维解法的方法一样。下面给出过程。
最开始我的写法是这样的(pre是二维数组):
for (int i=1;i<=n;i++) { for (int j=v;j>=data[i];j--) { if (dp[j]>dp[j-data[i]]+data[i]) { dp[j]=dp[j]; pre[i][j]=pre[i-1][j]; } else { dp[j]=dp[j-data[i]]+data[i]; pre[i][j]=pre[i-1][j-data[i]]|(1<<i); } } for (int j=0;j<data[i];j++) //需要将上一行的状态传递给下一行 pre[i][j]=pre[i-1][j]; }
然后优化到一维:
for (i=1;i<=n;i++) for (int j=v;j>=data[i];j--) if (dp[j]>dp[j-data[i]]+data[i]) { dp[j]=dp[j]; pre[j]=pre[j]; } else { dp[j]=dp[j-data[i]]+data[i]; pre[j]=pre[j-data[i]]|(1<<i); }
下面贴一份比赛中共享的一份代码,用另一种思路做的:
#include <stdio.h> #define max 1000005 int f[max][25]; //f[i][j]到达i状态时j是否使用 int main () { int n; int t; int a[25]; int i,j,l; int ans; while(scanf("%d",&n)!=EOF) { ans=0; scanf("%d",&t); for(i=1;i<=t;i++) scanf("%d",&a[i]); for(i=0;i<=n;i++) for(j=0;j<=t;j++) f[i][j]=0; f[0][0]=1; for (i=1;i<=t;i++) //1~t物品标号 for (j=n-a[i];j>=0;j--) { if (f[j][0]==0) continue; f[j+a[i]][0]=1; for (l=1;l<=t;l++) f[j+a[i]][l]=f[j][l]; f[j+a[i]][i]=1; if (j+a[i]>ans) ans=j+a[i]; } for (i=1;i<=t;i++) if (f[ans][i]) printf("%d ",a[i]); printf("sum:%d\n",ans); } return 0; }
在贴一份网上的解法,和我最开始的思路一样,不过当时我没有实现出来……
http://www.cppblog.com/syhd142/articles/118968.html
相关文章推荐
- UVA 题目624 CD(01背包输出路径啊)
- uva 624 CD 01背包打印路径
- UVA 624 CD(01背包+输出方案)
- UVA 624 CD(01背包,要记录路径)
- UVA 624 CD(01背包输出)
- uva 624 CD 01背包打印路径
- uva 624 CD 01背包状态压缩记路径
- UVA 624 - CD (01背包打印路径)
- uva 624 CD(01背包 路径记录)
- 【uva】624 CD【背包记录路径】
- uva 624 CD (0-1背包打印路径)
- uva624 CD(dp 0-1 背包 打印路径)
- CD-----UVa624(01背包+输出路径)
- UVA 624CD(01背包输出 + 输出路径)
- uva624 CD (01背包+路径的输出)
- UVA 624 CD (01 背包)
- UVA 624 - CD (01背包 + 打印物品)
- UVA 624(01背包记录路径)
- UVA624(01背包 + 路径打印)
- UVA - 624 - CD(动态规划,背包,打印路径)