vijos1020—切蛋糕
2016-05-03 21:28
337 查看
题目
方法:二分+dfs+剪枝
这方面的c++实现是第一次,脑子一片混沌,后来参照大神代码才明白。
二分最多满足几个嘴巴,相当于定了下界,再dfs验证。
关键是剪枝:
1.以最小的嘴累加,与蛋糕总和比较,找到最多能满足的嘴数,就是二分上边界。
2.dfs时记录当前浪费的蛋糕和,总蛋糕量-当前浪费的蛋糕和<当前二分的要满足的嘴大小和,就说明无法满足,则退出。
3.dfs时若当前嘴巴大小与下一个相同,则下一个无需从蛋糕1开始枚举,直接从当前嘴巴枚举的蛋糕i开始。
尽管知道怎么做,还是调了好久的代码= =。
二分需要注意,要想清楚输出什么,举几个特殊例子调整left,right的更新。
递归边界要写“<”虽然不知道为什么。。但少了就不行了。。。
一开始把剪枝2写成了sum[m]竟然只有三个点wa,不得不说vijos的数据太水了吧。
方法:二分+dfs+剪枝
这方面的c++实现是第一次,脑子一片混沌,后来参照大神代码才明白。
二分最多满足几个嘴巴,相当于定了下界,再dfs验证。
关键是剪枝:
1.以最小的嘴累加,与蛋糕总和比较,找到最多能满足的嘴数,就是二分上边界。
2.dfs时记录当前浪费的蛋糕和,总蛋糕量-当前浪费的蛋糕和<当前二分的要满足的嘴大小和,就说明无法满足,则退出。
3.dfs时若当前嘴巴大小与下一个相同,则下一个无需从蛋糕1开始枚举,直接从当前嘴巴枚举的蛋糕i开始。
尽管知道怎么做,还是调了好久的代码= =。
#include<iostream> #include<algorithm> using namespace std; int cake[55],fcake[55],sum[1025],mou[1025],n,m,mid,space,tot=0; int cmp(const void *a, const void *b) { return(*(int *)a-*(int *)b); } bool dfs(int deep,int pos) { if(deep<=0) return 1; //递归边界 if(tot-space<sum[mid]) return 0;//剪枝2 for(int i=pos;i<=n;i++) if(fcake[i]>=mou[deep]) { fcake[i]-=mou[deep]; if(fcake[i]<mou[1]) space+=fcake[i]; if(mou[deep]==mou[deep-1]) //剪枝3 { if(dfs(deep-1,i)) return 1; } else if(dfs(deep-1,1)) return 1; if(fcake[i]<mou[1]) space-=fcake[i]; fcake[i]+=mou[deep]; } return 0; } int main() { int i; cin>>n; for(i=1;i<=n;i++) { cin>>cake[i]; tot+=cake[i]; } cin>>m; for(i=1;i<=m;i++) cin>>mou[i]; qsort(cake+1,n,sizeof(int),cmp); qsort(mou+1,m,sizeof(int),cmp); sum[0]=0; for(i=1;i<=m;i++) sum[i]=sum[i-1]+mou[i]; while(sum[m]>tot) m--;//剪枝1 int left=1,right=m; mid=((left+right)>>1); while(left<=right) { for(i=1;i<=n;i++) fcake[i]=cake[i]; space=0; if(dfs(mid,1)) left=mid+1; else right=mid-1; mid=((left+right)>>1); } cout<<mid<<endl; return 0; }
二分需要注意,要想清楚输出什么,举几个特殊例子调整left,right的更新。
递归边界要写“<”虽然不知道为什么。。但少了就不行了。。。
一开始把剪枝2写成了sum[m]竟然只有三个点wa,不得不说vijos的数据太水了吧。
相关文章推荐
- VIJOS P1040 高精度乘法
- VIJOS P1000 A+B Problem
- vijos P1051 送给圣诞夜的极光
- vijos P1134 矩形覆盖 题解
- vijos P1131 最小公倍数和最大公约数问题 题解
- vijos P1320 清点人数 题解
- vijos P1597 2的幂次方 题解(递归)
- vijos P1134 算24点 题解
- vijos1057
- Vijos P1775 乌龟棋 题解
- Vijos P1133 装箱问题 题解
- Vijos P1098 合唱队形题解
- 孙子定理(中国剩余定理)
- 扩展欧几里德
- 第七讲 有依赖的背包问题 vijos P1313金明的预算方案
- 第一讲 01背包问题 vijos P1025小飞侠的游园方案
- vijos P1059积木城堡
- vijos P1071新年趣事之打牌
- 【vijos】P1016北京2008的挂钟
- 【vijos】P1082丛林探险DFS+剪枝版本