描述

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[复制]

5
1 3 4 5 2

样例输出1[复制]

7

来源

某校NOIP模拟题

很容易地敲出了暴力代码

j=dfs(l1,l2,cur)
{
if cur==n+1
if l1==l2 then record(l1)
exit
dfs(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

 
100
0 536 ksq2013 C++ 2016-08-18 22:36:20
#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[][];
int n,h[],tot;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&h[i]);
tot+=h[i];
}
for(int i=;i<=;i++)
for(int j=;j<=tot;j++)
f[i][j]=-0x3f3f3f3f;
int t=;
for(int i=;i<=n;i++){
t^=;
for(int j=h[i];j<=tot;j++)
f[t][j]=mx(f[t][j],f[^t][j-h[i]]);
for(int j=;j<=tot-h[i];j++)
f[t][j]=mx(f[t][j],f[^t][j+h[i]]+h[i]);
for(int j=;j<h[i];j++)
f[t][j]=mx(f[t][j],f[^t][h[i]-j]+h[i]-j);
for(int j=;j<=tot;j++)
f[^t][j]=f[t][j];
}
if(f[^t][])
printf("%d\n",f[^t][]);
else puts("Impossible");
return ;
}

其实这样写更直观

#include<iostream>
using namespace std;
int n,h[],tot;
bool f[][];
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=;i<=n;i++)
cin>>h[i],
tot+=h[i];
f[][]=;
tot>>=;
for(int k=;k<=n;k++)
for(int i=tot;i>=;i--)
for(int j=tot;j>=;j--){
if(i-h[k]>=&&f[i-h[k]][j])f[i][j]=;
else if(j-h[k]>=&&f[i][j-h[k]])f[i][j]=;
}
for(int i=tot;i>=;i--)
if(f[i][i]){
cout<<i<<endl;
return ;
}
cout<<"Impossible"<<endl;
return ;
}

vijos1037搭建双塔(一维背包问题)的更多相关文章

  1. vijos P1037搭建双塔

    P1037搭建双塔 Accepted 标签:动态规划 背包     描述 2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难.为了纪念“9?11”事件, ...

  2. vijosP1037搭建双塔

    vijosP1037搭建双塔 链接:https://vijos.org/p/1037 [思路] DP. [代码] #include<iostream> #include<cstrin ...

  3. tyvj1114 搭建双塔

    描述     2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难.为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔.    Mr. F有 ...

  4. VIJOS P1037搭建双塔[DP]

    描述 2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难.为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔. Mr. F有N块水晶,每块 ...

  5. 搭建双塔(vijos 1037)

    描述 2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难.为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔. Mr. F有N块水晶,每块 ...

  6. 【动态规划】Vijos P1037 搭建双塔

    题目链接: https://vijos.org/p/1037 题目大意: 给n块砖的长度(n<=100),问从中任选m块砖能否建成2个相同高度的塔. 能的话求最高高度,不能输出 Impossib ...

  7. 备战NOIP每周写题记录(一)···不间断更新

    ※Recorded By ksq2013 //其实这段时间写的题远远大于这篇博文中的内容,只不过那些数以百记的基础题目实在没必要写在blog上; ※week one 2016.7.18 Monday ...

  8. dp式子100个……

    1.        资源问题1-----机器分配问题F[I,j]:=max(f[i-1,k]+w[i,j-k]) 2.        资源问题2------01背包问题F[I,j]:=max(f[i- ...

  9. dp方程

    1.        资源问题1 -----机器分配问题 F[I,j]:=max(f[i-1,k]+w[i,j-k]) 2.        资源问题2 ------01背包问题   F[I,j]:=ma ...

随机推荐

  1. putty不能连接linxu,报:connection refused

    用putty连接新装的centos6.5,出现了connection refused问题, 后参考http://blog.sina.com.cn/s/blog_60d2d62a0100tq2l.htm ...

  2. ubuntu环境变量

    在Ubuntu中有如下几个文件可以设置环境变量1./etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.2. ...

  3. oracle中Window和Window Group

    参考文献: http://www.5ienet.com/note/html/scheduler/oracle-scheduler-using-window.shtml window概念 此Window ...

  4. '[<NSObject 0x8a4b500> setValue:forUndefinedKey:]

    Bug如下: Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUnd ...

  5. sqlite锁的机制

     reserved state 进入reserved state以后,sqlite可以修改数据库中的内容,不过把修改以后的内容写到pager的缓存里,大小由page cache指定. 进入这个状态以 ...

  6. Android微信登陆

    前言 分享到微信朋友圈的功能早已经有了,但微信登录推出并不久,文档写的也并不是很清楚,这里记录分享一下. 声明 欢迎转载,但请保留文章原始出处:)  博客园:http://www.cnblogs.co ...

  7. CEF3可行性

    Chromium Embedded Framework 顾名思义,内嵌式CHROME,详细的介绍参阅 http://yogurtcat.com/posts/cef/hello-cef.html 为什么 ...

  8. android Gui系统之SurfaceFlinger(2)---BufferQueue

    6 BufferQueue 上一篇已经说到,BufferQueue是SurfaceFlinger管理和消费surface的中介,我们就开始分析bufferqueue. 每个应用 可以由几个Buffer ...

  9. @在php中的作用

    @是PHP提供的错误信息屏蔽的专用符号. 使用@mysql_query 不会出现Warning,而原来mysql_query 在遇到错误时会在页面上访提示Warning. 看PHP的代码,总有些行前边 ...

  10. ORACLE查看数据文件包含哪些对象

    在上篇ORACLE查看表空间对象中,我介绍了如何查询一个表空间有那些数据库对象,那么我们是否可以查看某个数据文件包含那些数据库对象呢?如下所示 SELECT  E.SEGMENT_TYPE       ...