多组测试数据(<=1500)。数据以EOF结尾 第一行输入西瓜数量N (1 ≤ N ≤ 20) 第二行有N个数,W1, …, Wn (1 ≤ Wi ≤ 10000)分别代表每个西瓜的重量
输出
输出分成两堆后的质量差
样例输入
5
5 8 13 27 14
样例输出
3
思路:刚开始的dfs超时了好长时间,跟大神交流完全听不懂,还是太菜了;直接贴代码吧;
自己的代码:#include<stdio.h> #include<algorithm> using namespace std; int melon[21],N,dd,sum; void birth(int i,int teamer){ if(i<=N){ int x=sum-2*teamer; if(x<0)x=-x; dd=x<dd?x:dd; if(teamer>sum/2.0)return; birth(i+1,teamer+melon[i+1]); birth(i+1,teamer); }} int main(){ while(~scanf("%d",&N)){sum=0; for(int i=1;i<=N;++i)scanf("%d",&melon[i]),sum+=melon[i]; sort(melon+1,melon+N+1); dd=sum; birth(0,0); printf("%d\n",dd); } return 0; }
大神的代码://虽然没有看懂;
//计科14-3陈振宇 2015/7/12 23:19:10 #include<stdio.h> #include<math.h> #include <cstring> #include<algorithm> using namespace std; int melon[21],N,dd,sum; int vis[21]; int ans; void birth(int pos, int len)//当前搜索位置 当前西瓜总质量 { ans = min(abs(sum - len * 2), ans);//更新 if(pos == N+1) return ; if(len > sum / 2) return ;//剪枝 升序排列 当前已经超了 再往后搜也必超 for(int i = pos; i <= N; i++) { if(vis[i]) continue; vis[i] = 1; birth(i+1, len+melon[i]); while(melon[i] == melon[i+1])//剪枝去掉后面与该西瓜质量相等的 题目数据不好这一步应该有用的 结果加上反而多了100ms ++i; vis[i] = 0; } } int main() { while(~scanf("%d",&N)) { sum=0; for(int i=1;i<=N;++i) scanf("%d",&melon[i]),sum+=melon[i]; sort(melon+1, melon+N+1);//升序排序 质量大的西瓜影响大 剪枝 ans = 10000000; memset(vis, 0, sizeof(vis)); birth(1, 0);//当前位置 当前长度 printf("%d\n", ans); } return 0; }
刚开始自己参考的大神代码://虽然没剪枝,但时间运行却最短,没找出来原因;
#include<stdio.h> #include<math.h> int a[10000]; int dd;//用dd来保存最小差 void fun(int sum,int cur,int m,int i) { if (i<m)//最多选m个 { //假设cur为其中一个的分得的和,如,sum=67,cur=35,t1=-3; int t1=sum-2*cur; if (t1<0) t1=-t1; if (t1<dd) //记下最小的t1; dd=t1; fun(sum,cur+a[i+1],m,i+1);//选a[i+1] fun(sum,cur,m,i+1);//不选a[i+1]; } } int main() { int m; int i,j,sum=0; while (scanf("%d",&m)!=EOF) { sum=0; for (i=0;i<m;i++) { scanf("%d",&a[i]); sum=sum+a[i]; } dd=sum; fun(sum,a[0],m,0); printf("%d\n",dd); } return 0; }