博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【洛谷 P1651】 塔 (差值DP)
阅读量:6688 次
发布时间:2019-06-25

本文共 1385 字,大约阅读时间需要 4 分钟。

题意:\(n\)个木块放到两个塔里,每个木块可放可不放,使得两塔高度相同且高度最大,求最大高度。
这个差值\(DP\)的思维难度还是很大的,没想出来,我就打了一个\(dfs\)骗了好像\(20\)还是\(30\)分吧(看来搜索也写挂)。
正解是\(DP\)\(f[i][j]\)表示前\(i\)块木块使得两个塔的高度差为\(k\)时高度最大的那个是什么(神奇的状态)
那么无非就\(4\)种情况:
1、第\(i\)块不放:\(f[i][j]=f[i-1][j]\)
2、第\(i\)块放到矮的上面,矮的仍然矮:\(f[i][j]=f[i-1][j+a[i]]\)
3、第\(i\)块放到高的上面,高的当然高:\(f[i][j]=f[i-1][j-a[i]]+a[i]\)
4、第\(i\)块放到矮的上面,矮的变高的:\(f[i][j]=f[i-1][a[i]-j]+j\)
可以发现,\(f[i]\)的取值仅与\(f[i-1]\)有关,于是第一维是可以滚掉的。

#include 
#include
#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);#define Close fclose(stdin);fclose(stdout);const int MAXN = 55;const int MAX = 500010;int dp[MAX][2];inline int max(int a, int b){ return a > b ? a : b;}int n, s[MAXN], sum;int main(){ Open("tower"); scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &s[i]), sum += s[i]; memset(dp, 128, sizeof dp); dp[0][0] = dp[0][1] = 0; for(int i = 1; i <= n; ++i) for(int j = sum; ~j; --j){ dp[j][i%2] = dp[j][!(i%2)]; if(j + s[i] <= sum) dp[j][i%2] = max(dp[j][i%2], dp[j + s[i]][!(i%2)]); if(j - s[i] >= 0) dp[j][i%2] = max(dp[j][i%2], dp[j - s[i]][!(i%2)] + s[i]); if(j < s[i]) dp[j][i%2] = max(dp[j][i%2], dp[s[i] - j][!(i%2)] + j); } printf("%d\n", !dp[0][n%2] ? -1 : dp[0][n%2]); Close; return 0;}

转载于:https://www.cnblogs.com/Qihoo360/p/9660248.html

你可能感兴趣的文章
ubuntu 安装过程记录
查看>>
my blog zen :分享所学,backup一切~
查看>>
JAVA上加密算法的实现用例MD5/SHA1,DSA,DESede/DES,Diffie-Hellman的使用(转)
查看>>
武侠-event
查看>>
学习C# delegate和C# event
查看>>
把XML文件转换为字符串
查看>>
AD域的唯一ID字段uSNCreated
查看>>
Ubuntu 12.04中文输入法的安装
查看>>
Linux MySQL-Workbench安装
查看>>
jQuery的.live()和.die()[转]
查看>>
hdu_2002_计算球体积_解题报告
查看>>
连接数据库通过配置文件app.config
查看>>
赛星软件---智能视频分析事件检测
查看>>
【二叉树遍历】中序
查看>>
一个完整的类用来读取OpenSSL生成的pem格式的x509证书
查看>>
Delphi调用WebService(通过SoapHeader认证)经验总结
查看>>
2014年最新世界各国面积排名(172个国家)
查看>>
socket编程演示样例(多线程)
查看>>
C++ 初始化与赋值
查看>>
碰到的异常
查看>>