poj1014 - Dividing
来源:互联网 发布:java线程超时关闭 编辑:程序博客网 时间:2024/05/16 15:05
想看更多的解题报告:http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:
有六个大理石,他们的价值分别是1,2,3,4,5,6,然后分别给出六个大理石的个数,问如何平分给两个人,令两个人所得到的价值相等。
前面想到了DFS,写了一个裸的DFS,结果TLE,结果不断剪枝,还是TLE,后来觉得已经无法再剪枝了,但是却WE了,后来看了一位大神的,他的和我的只有一个地方不同,以下两段代码,我改了一个地方就A了,但是其实质上没什么区别,所以我认为这题用DFS还是不能过的。应该用DP是对的。
这是A了的:
#include <iostream>using namespace std;int a[7],sum;int dfs(int cap,int value){int i,temp;if(value==sum) return 1;for(i=cap;i>=1;i--)if(a[i]){temp=value+i;if(temp<=sum){a[i]--;if(dfs(i,temp)) return 1;}}return 0;}int main(){int flag,i,t;for(t=1;;t++){for(flag=sum=0,i=1;i<=6;i++){scanf("%d",&a[i]);sum+=i*a[i];if(!flag && a[i]) flag=1;}if(!flag) break;printf("Collection #%d:\n",t);if(sum&1){printf("Can't be divided.\n\n");continue;}sum=sum>>1;if(dfs(6,0))printf("Can be divided.\n\n");elseprintf("Can't be divided.\n\n");}return 0;}
这是WE的:
#include <iostream>using namespace std;int a[7],sum;int dfs(int cap,int value){int i,temp;if(value==sum) return 1;for(i=cap;i<=6;i++)if(a[i]){temp=value+i;if(temp<=sum){a[i]--;if(dfs(i,temp)) return 1;}}return 0;}int main(){int flag,i,t;for(t=1;;t++){for(flag=sum=0,i=1;i<=6;i++){scanf("%d",&a[i]);sum+=i*a[i];if(!flag && a[i]) flag=1;}if(!flag) break;printf("Collection #%d:\n",t);if(sum&1){printf("Can't be divided.\n\n");continue;}sum=sum>>1;if(dfs(1,0))printf("Can be divided.\n\n");elseprintf("Can't be divided.\n\n");}return 0;}
下面是模拟多重背包问题,总共6个物品,将第i个物品的价值与费用都看做是i,这样套用背包九讲的多重背包模板就可以了,不过注意的是数组要开的大一点.
#include <iostream>using namespace std;#define MAXV 100005#define INF 100000000#define max(a,b) a>b?a:bint sum,a[7],f[MAXV];void CompletePack(int cost,int weight){int i;for(i=cost;i<=sum;i++){f[i]=max(f[i],f[i-cost]+weight);}}void ZeroOnePack(int cost,int weight){int i;for(i=sum;i>=cost;i--){f[i]=max(f[i],f[i-cost]+weight);}}void MultiplePack(int cost,int weight,int amount){if(cost*amount>=sum){CompletePack(cost,weight);return ;}int k=1;while(k<amount){ZeroOnePack(k*cost,k*weight);amount-=k;k=k<<1;}ZeroOnePack(amount*cost,amount*weight);}void dp(){int i,j,k;for(i=1;i<=sum;i++) f[i]=-INF;f[0]=0;for(i=1;i<=6;i++)MultiplePack(i,i,a[i]);}int main(){int flag,i,t;for(t=1;;t++){for(flag=sum=0,i=1;i<=6;i++){scanf("%d",&a[i]);sum+=i*a[i];if(!flag && a[i]) flag=1;}if(!flag) break;printf("Collection #%d:\n",t);if(sum&1){printf("Can't be divided.\n\n");continue;}sum=sum>>1;dp();if(f[sum]>=0)printf("Can be divided.\n\n");elseprintf("Can't be divided.\n\n");}return 0;}
上面是用“拆分法”来做的,不过应为题目是一个可行性问题,即状态只有两种,是否可行,现在用一种O(VN)的算法来写,上面O(V*∑logn[i])跑了16MS,现在用这种算法只跑了0MS。或许是这题的数据太弱了吧。
#include <iostream>using namespace std;#define MAXV 100005#define INF 100000000#define max(a,b) a>b?a:bint sum,a[7],ans,f[MAXV],t[MAXV];void dp(){int i,j,k;memset(f,0,sizeof(f));//用1表示可行,0表示不行f[0]=1;for(i=1;i<=6;i++){memset(t,0,sizeof(t));for(j=i;j<=sum;j++){if(!f[j] && f[j-i] && t[j-i]+1<=a[i]){f[j]=1;t[j]=t[j-i]+1;}}}}int main(){int flag,i,t;for(t=1;;t++){for(flag=sum=0,i=1;i<=6;i++){scanf("%d",&a[i]);sum+=i*a[i];if(!flag && a[i]) flag=1;}if(!flag) break;printf("Collection #%d:\n",t);if(sum&1){printf("Can't be divided.\n\n");continue;}sum=sum>>1;dp();if(f[sum])printf("Can be divided.\n\n");elseprintf("Can't be divided.\n\n");}return 0;}
- poj1014 - Dividing
- poj1014:Dividing
- POJ1014 Dividing
- poj1014 Dividing
- POJ1014 Dividing
- poj1014-Dividing
- POJ1014:Dividing
- POJ1014:Dividing
- 【poj1014】 Dividing
- poj1014 Dividing题解
- poj1014——Dividing
- poj1014 hdu1059 Dividing
- POJ1014--多重背包--Dividing
- poj1014 &&hdu 1059dividing
- POJ1014 & HDU1059 Dividing
- POJ1014 Dividing 母函数
- POJ1014——Dividing
- poj1014 Dividing(背包)
- JFreeChart的使用
- 第十五周实验报告 任务二
- MeasureSpec介绍及使用详解
- 一些代码优化的方法
- Spring3 @Transaction
- poj1014 - Dividing
- php 递归 实现无限分类 格式化数组
- 新建网站方式
- --利用Linux恢复数据的方法
- Hibernate关联关系配置(一对多、一对一和多对多)
- MyEclipse 9.1优化技巧
- 黑马程序员_单例模式
- 学术搜索引擎大全(转自:http://scienceroom.net/scholar-search-engines)
- EXTJS 中Grid控件的常用代码