UVALive 4625 Garlands(二分答案 + DP)
来源:互联网 发布:天弘基金官网淘宝店 编辑:程序博客网 时间:2024/05/06 13:24
题目大意:给你一串 n 个数,表示n个球,给你这n个球的重量,要你把这n个数分成 m - 1 段,每段的数字个数都是偶数,对于每一段,它的半段数字个数都不超过d,找出一种分发,使所有的这些半段的重量的最小值,并输出这个最小值。
思路:如果单纯从DP方面考虑,那么设状态量 d[ i ][ j ] 表示前 i 个,分成 j 段的最小值,那么复杂度是 O(n*m*d)肯定爆掉。所以这道题有一个非常巧妙的解法,那就是二分答案。
当确定当前二分值 x 时,对原序列进行DP,设d[ i ] 表示前分 i 个数字的半段最大值都不超过 x 的最小段数,然后 d[ i ] = min(d[ i ] ,d[ j ] +1),i、j之间满足上述的偶数、d、x这些条件 ,可以枚举半段长度 len 。但是这样之后还有一个问题,那就是对于第三组样例 1 1 100 100 1 1 ,m = 3(即分为2段),会发现,如果 x == 102 ,那么它的最小段数是 1 ,能分成 1 段,并不意味着它一定能分成 2 段。这里还有一点,那就是奇偶性,对于已经分出的一段,它的长度是偶数,我们找到它的中点,从中点向两边再分出 1 段,那么就相当于把本来的1 段分成了 3 段,增加了 2 段,如果你直接把两边那两段直接搞成长度是 2 的,那么就可以一直那么分下去,也就是说,奇数段一定能分成奇数段,偶数段一定能分成偶数段。所以,我们再进行上述DP的时候,还要在开一维,用来表示奇偶,状态转移方程为 : d[ i ][ j ] = min( d[ k ][ ~j ] + 1 ),i、k 满足关系。
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF = 0x0fffffff ;const int MAXN = 40004 ;int w[MAXN],sum[MAXN];int n,m,d;int dp[MAXN][2];int check(int x){ dp[0][0] = 0; dp[0][1] = INF; for(int i = 2 ; i <= n ; i += 2) { dp[i][0] = INF; dp[i][1] = INF; for(int len = 1;len <= d && i -2*len >= 0 ;len++) { if(sum[i] - sum[i - len] > x ) break; if(sum[i - len] - sum[i - 2*len] <= x) { dp[i][0] = min(dp[i][0],dp[i - 2*len][1] + 1); dp[i][1] = min(dp[i][1],dp[i - 2*len][0] + 1); } } } if(dp[n][(m-1)%2] > m-1) return 0; else return 1;}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&d); sum[0] = 0; for(int i = 1;i<=n;i++) { scanf("%d",&w[i]); sum[i] = sum[i-1] + w[i]; } if(n&1) { puts("BAD"); } else if(n < 2*(m-1)) { puts("BAD"); } else if(n > 2*d*(m-1)) { puts("BAD"); } else { int l = 1, r = sum[n]; while(l<r) { int m = l+r >>1; if(check(m)) { r = m; } else l = m+1; } printf("%d\n",l); } } return 0;}
- UVALive 4625 Garlands(二分答案 + DP)
- UVALive 4625 Garlands(dp+二分)
- UVALive 3608 Period(二分答案+DP)
- UVA - 1443 Garlands (二分+DP)
- Garlands - UVa 1443 二分+dp
- UVALive 5983 MAGRID(二分+dp)
- UVALive 3608 Period(DP+二分)
- UVALive 3635 Pie (二分答案)
- UVALive 6442 Coins on a Ring(二分查找答案)
- so就 (二分答案 dp 贪心)
- 道路覆盖 (二分答案+状压DP)
- 【dp/二分+暴力】MAGRID UVALive
- hdu3586(树形DP+二分答案)
- Topcoder SRM658,DP+二分答案,
- 二分答案加DP判断
- [dp][二分答案]最大正方形
- bzoj4985 评分(二分答案+dp)
- Codeforces#374(div2)- C. Journey(二分答案+dp)
- eclipse启动android程序,如何指定模拟器
- POJ2299-归并排序
- linux 下eclipse 配置android
- php的一些常识问题,我觉得还是有用的,所以,我觉得要学习哦!
- 小米笔试题之unsigned int 与int的转换问题
- UVALive 4625 Garlands(二分答案 + DP)
- 递归--目录操作及无限级分类之子孙树应用
- 文件操作
- poj 1990
- JavaScript特点及函数
- Tomcat与web程序结构与Http协议
- 2013/8/12--2013/8/18 总结
- Hibernate学习录
- V8实例分析