vijos1037搭建双塔(一维背包问题)
来源:互联网 发布:中金公司 知乎 编辑:程序博客网 时间:2024/06/08 03:24
描述
2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难。为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔。
Mr. F有N块水晶,每块水晶有一个高度,他想用这N块水晶搭建两座有同样高度的塔,使他们成为一座双塔,Mr. F可以从这N块水晶中任取M(1≤M≤N)块来搭建。但是他不知道能否使两座塔有同样的高度,也不知道如果能搭建成一座双塔,这座双塔的最大高度是多少。所以他来请你帮忙。
给定水晶的数量N(1≤N≤100)和每块水晶的高度Hi(N块水晶高度的总和不超过2000),你的任务是判断Mr. F能否用这些水晶搭建成一座双塔(两座塔有同样的高度),如果能,则输出所能搭建的双塔的最大高度,否则输出“Impossible”。
格式
输入格式
输入的第一行为一个数N,表示水晶的数量。第二行为N个数,第i个数表示第i个水晶的高度。
输出格式
输出仅包含一行,如果能搭成一座双塔,则输出双塔的最大高度,否则输出一个字符串“Impossible”。
样例1
样例输入1[复制]
51 3 4 5 2
样例输出1[复制]
7
来源
某校NOIP模拟题
很容易地敲出了暴力代码
j=dfs(l1,l2,cur){if cur==n+1if l1==l2 then record(l1)exitdfs(l1+h[cur],l2,cur+1)dfs(l1,l2+h[cur],cur+1)dfs(l1,l2,cur+1)}于是自己愚蠢地写了一个动规代码
dp()for(i->1 to n)for(j->tot/2 to h[i])f[i][j]=f[i-1][j]if(f[i-1][j-h[i]])if f[i-1][j] then record(j)f[i][j]=1然而思路是错的,得分:30。
测试数据 #0: Accepted, time = 0 ms, mem = 516 KiB, score = 10
测试数据 #1: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0
测试数据 #2: WrongAnswer, time = 15 ms, mem = 516 KiB, score = 0
测试数据 #3: WrongAnswer, time = 0 ms, mem = 512 KiB, score = 0
测试数据 #4: Accepted, time = 0 ms, mem = 520 KiB, score = 10
测试数据 #5: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0
测试数据 #6: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0
测试数据 #7: Accepted, time = 0 ms, mem = 516 KiB, score = 10
测试数据 #8: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0
测试数据 #9: WrongAnswer, time = 0 ms, mem = 512 KiB, score = 0
WrongAnswer, time = 15 ms, mem = 520 KiB, score = 30
标准解法:令f[i][j]为前i块水晶搭成的双塔高度差为j时,最矮的塔的高度的max值。
为转移f[i][j],我们先列出一下策略:
1.不选该水晶块,此时直接继承,f[i][j]->f[i-1][j],此时的高度不变
2.选择该水晶块,放在原本就高的塔上,f[i][j]=f[i-1][j-h[i]]
3.选择该水晶块,放在原本就小的塔上,则:
(1.小的还是小的,那么f[i][j]=f[i-1][j+h[i]]+h[i]
(2.小的成为了大的,那么f[i][j]=f[i-1][h[i]-j]+h[i]-j
Qed!
代码:
Accepted
#include<stdio.h>#include<stdlib.h>using namespace std;inline int mx(int x,int y){ if(x>y)return x; return y;}int f[3][2001];int n,h[201],tot;int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&h[i]); tot+=h[i]; } for(int i=0;i<=1;i++) for(int j=1;j<=tot;j++) f[i][j]=-0x3f3f3f3f; int t=1; for(int i=1;i<=n;i++){ t^=1; for(int j=h[i];j<=tot;j++) f[t][j]=mx(f[t][j],f[1^t][j-h[i]]); for(int j=0;j<=tot-h[i];j++) f[t][j]=mx(f[t][j],f[1^t][j+h[i]]+h[i]); for(int j=0;j<h[i];j++) f[t][j]=mx(f[t][j],f[1^t][h[i]-j]+h[i]-j); for(int j=0;j<=tot;j++) f[1^t][j]=f[t][j]; } if(f[1^t][0]) printf("%d\n",f[1^t][0]); else puts("Impossible"); return 0;}(注:此题解法很特殊,不过也有直观思路,博文上就不提及了)
- vijos1037搭建双塔(一维背包问题)
- [Vijos1037]搭建双塔
- vijos1037-搭建双塔
- [vijos1037]搭建双塔
- vijos1037 双塔问题
- 【DP】【vijos1037】搭建双塔
- Cpp环境【Vijos1037】【CQYZos1391】搭建双塔
- vijos1037 搭建双塔-状态优化dp
- vijos1037 搭建双塔(重庆一中高2018级信息学竞赛测验7) 解题报告
- 背包问题(一)
- 背包问题(一维dp)
- 背包问题(一):完全背包
- (背包一)0-1背包问题
- 背包问题(01背包和完全背包)一维数组实现
- vijosp1037-类背包问题&好题-搭建双塔
- 动态规划之背包问题(一):01背包问题
- 0-1背包问题(一维数组解法)
- 简单01背包问题 一维解决方法
- HDU 5860 Death Sequence(递推)
- 查询python已导入的modules 以及 如何取消已导入的modues
- LightOJ - 1138 Trailing Zeroes (III)
- hive加载数据
- JVM Attach机制实现
- vijos1037搭建双塔(一维背包问题)
- 1026. 程序运行时间(15)
- web前端开发遇到问题记录
- 基于Yahoo网站性能优化的34条军规及自己的见解
- Sunshine’s city(lct+线段树)
- Triangle leetcode
- PHP爬取百度图片
- 2016.08.18【初中部 NOIP普及组 】模拟赛
- redis集群方案-一致性hash算法