首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐
2025年6月1日 星期日 8:32am

poj1014 - Dividing

  • 24-03-05 06:41
  • 2547
  • 13553
blog.csdn.net

                                    想看更多的解题报告: http://iyenn.com/rec/1824570.html
                                     转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:

有六个大理石,他们的价值分别是1,2,3,4,5,6,然后分别给出六个大理石的个数,问如何平分给两个人,令两个人所得到的价值相等。

 

前面想到了DFS,写了一个裸的DFS,结果TLE,结果不断剪枝,还是TLE,后来觉得已经无法再剪枝了,但是却WE了,后来看了一位大神的,他的和我的只有一个地方不同,以下两段代码,我改了一个地方就A了,但是其实质上没什么区别,所以我认为这题用DFS还是不能过的。应该用DP是对的。

这是A了的:

  1. #include
  2. using namespace std;
  3. int a[7],sum;
  4. int dfs(int cap,int value){
  5. int i,temp;
  6. if(value==sum) return 1;
  7. for(i=cap;i>=1;i--)
  8. if(a[i]){
  9. temp=value+i;
  10. if(temp<=sum){
  11. a[i]--;
  12. if(dfs(i,temp)) return 1;
  13. }
  14. }
  15. return 0;
  16. }
  17. int main(){
  18. int flag,i,t;
  19. for(t=1;;t++){
  20. for(flag=sum=0,i=1;i<=6;i++){
  21. scanf("%d",&a[i]);
  22. sum+=i*a[i];
  23. if(!flag && a[i]) flag=1;
  24. }
  25. if(!flag) break;
  26. printf("Collection #%d:\n",t);
  27. if(sum&1){
  28. printf("Can't be divided.\n\n");
  29. continue;
  30. }
  31. sum=sum>>1;
  32. if(dfs(6,0))
  33. printf("Can be divided.\n\n");
  34. else
  35. printf("Can't be divided.\n\n");
  36. }
  37. return 0;
  38. }

这是WE的:

 

  1. #include
  2. using namespace std;
  3. int a[7],sum;
  4. int dfs(int cap,int value){
  5. int i,temp;
  6. if(value==sum) return 1;
  7. for(i=cap;i<=6;i++)
  8. if(a[i]){
  9. temp=value+i;
  10. if(temp<=sum){
  11. a[i]--;
  12. if(dfs(i,temp)) return 1;
  13. }
  14. }
  15. return 0;
  16. }
  17. int main(){
  18. int flag,i,t;
  19. for(t=1;;t++){
  20. for(flag=sum=0,i=1;i<=6;i++){
  21. scanf("%d",&a[i]);
  22. sum+=i*a[i];
  23. if(!flag && a[i]) flag=1;
  24. }
  25. if(!flag) break;
  26. printf("Collection #%d:\n",t);
  27. if(sum&1){
  28. printf("Can't be divided.\n\n");
  29. continue;
  30. }
  31. sum=sum>>1;
  32. if(dfs(1,0))
  33. printf("Can be divided.\n\n");
  34. else
  35. printf("Can't be divided.\n\n");
  36. }
  37. return 0;
  38. }


 

 下面是模拟多重背包问题,总共6个物品,将第i个物品的价值与费用都看做是i,这样套用背包九讲的多重背包模板就可以了,不过注意的是数组要开的大一点.

  1. #include
  2. using namespace std;
  3. #define MAXV 100005
  4. #define INF 100000000
  5. #define max(a,b) a>b?a:b
  6. int sum,a[7],f[MAXV];
  7. void CompletePack(int cost,int weight){
  8. int i;
  9. for(i=cost;i<=sum;i++){
  10. f[i]=max(f[i],f[i-cost]+weight);
  11. }
  12. }
  13. void ZeroOnePack(int cost,int weight){
  14. int i;
  15. for(i=sum;i>=cost;i--){
  16. f[i]=max(f[i],f[i-cost]+weight);
  17. }
  18. }
  19. void MultiplePack(int cost,int weight,int amount){
  20. if(cost*amount>=sum){
  21. CompletePack(cost,weight);
  22. return ;
  23. }
  24. int k=1;
  25. while(k
  26. ZeroOnePack(k*cost,k*weight);
  27. amount-=k;
  28. k=k<<1;
  29. }
  30. ZeroOnePack(amount*cost,amount*weight);
  31. }
  32. void dp(){
  33. int i,j,k;
  34. for(i=1;i<=sum;i++) f[i]=-INF;
  35. f[0]=0;
  36. for(i=1;i<=6;i++)
  37. MultiplePack(i,i,a[i]);
  38. }
  39. int main(){
  40. int flag,i,t;
  41. for(t=1;;t++){
  42. for(flag=sum=0,i=1;i<=6;i++){
  43. scanf("%d",&a[i]);
  44. sum+=i*a[i];
  45. if(!flag && a[i]) flag=1;
  46. }
  47. if(!flag) break;
  48. printf("Collection #%d:\n",t);
  49. if(sum&1){
  50. printf("Can't be divided.\n\n");
  51. continue;
  52. }
  53. sum=sum>>1;
  54. dp();
  55. if(f[sum]>=0)
  56. printf("Can be divided.\n\n");
  57. else
  58. printf("Can't be divided.\n\n");
  59. }
  60. return 0;
  61. }

 

 

上面是用“拆分法”来做的,不过应为题目是一个可行性问题,即状态只有两种,是否可行,现在用一种O(VN)的算法来写,上面O(V*∑logn[i])跑了16MS,现在用这种算法只跑了0MS。或许是这题的数据太弱了吧。

 


 

  1. #include
  2. using namespace std;
  3. #define MAXV 100005
  4. #define INF 100000000
  5. #define max(a,b) a>b?a:b
  6. int sum,a[7],ans,f[MAXV],t[MAXV];
  7. void dp(){
  8. int i,j,k;
  9. memset(f,0,sizeof(f)); //用1表示可行,0表示不行
  10. f[0]=1;
  11. for(i=1;i<=6;i++){
  12. memset(t,0,sizeof(t));
  13. for(j=i;j<=sum;j++){
  14. if(!f[j] && f[j-i] && t[j-i]+1<=a[i]){
  15. f[j]=1;
  16. t[j]=t[j-i]+1;
  17. }
  18. }
  19. }
  20. }
  21. int main(){
  22. int flag,i,t;
  23. for(t=1;;t++){
  24. for(flag=sum=0,i=1;i<=6;i++){
  25. scanf("%d",&a[i]);
  26. sum+=i*a[i];
  27. if(!flag && a[i]) flag=1;
  28. }
  29. if(!flag) break;
  30. printf("Collection #%d:\n",t);
  31. if(sum&1){
  32. printf("Can't be divided.\n\n");
  33. continue;
  34. }
  35. sum=sum>>1;
  36. dp();
  37. if(f[sum])
  38. printf("Can be divided.\n\n");
  39. else
  40. printf("Can't be divided.\n\n");
  41. }
  42. return 0;
  43. }


 

注:本文转载自blog.csdn.net的wangjian8006的文章"http://blog.csdn.net/wangjian8006/article/details/7606410"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top