vijos p1037——搭建双塔
描述
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”。
dp[i][j]表示前i点高度差为j的方案数
由于j代表高度差,所以有4种情况:
放低塔但仍其为低塔,高度差减小、
放低塔但成为高塔、
放高塔,仍为高塔、
不放。
dp初值:先全部赋为负数,然后dp[1][0]赋为0
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1005;
4 const int maxh=2005;
5 int dp[maxn][maxh];//前i点高度差为j
6 int h[maxn];
7 int n,sum[maxn];
8 int main()
9 {
10 memset(dp,-0x7f,sizeof(dp));
11 scanf("%d",&n);
12 for(int i=1;i<=n;i++)
13 scanf("%d",&h[i]);
14 sort(h+1,h+n+1);
15 for(int i=1;i<=n;i++)
16 sum[i]=sum[i-1]+h[i];
17 dp[1][0]=0;dp[1][h[1]]=0;
18 for(int i=2;i<=n;i++)
19 for(int j=0;j<=sum[i];j++)
20 {
21 int h1=j;//不放
22 dp[i][j]=max(dp[i][j],dp[i-1][h1]);
23
24 int h2=j-h[i];//放高塔
25 if(h2>=0)
26 dp[i][j]=max(dp[i][j],dp[i-1][h2]);
27
28 int h3=h[i]-j;//放低塔使其成为高塔
29 if(h3>=0)
30 dp[i][j]=max(dp[i][j],dp[i-1][h3]+h3);
31
32 int h4=j+h[i];//放低塔仍为低塔
33 dp[i][j]=max(dp[i][j],dp[i-1][h4]+h[i]);
34 }
35 if(dp[n][0]<=0)printf("Impossible");
36 else printf("%d",dp[n][0]);
37 return 0;
38 }
【推荐】中国电信天翼云云端翼购节,2核2G云服务器一口价38元/年
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 聊一聊 C#前台线程 如何阻塞程序退出
· 几种数据库优化技巧
· 聊一聊坑人的 C# MySql.Data SDK
· 使用 .NET Core 实现一个自定义日志记录器
· [杂谈]如何选择:Session 还是 JWT?
· 一个.NET开源、易于使用的屏幕录制工具
· 【经验】几种数据库优化技巧
· C#中 Task 结合 CancellationTokenSource的妙用
· Superpower:一个基于 C# 的文本解析工具开源项目
· 反微服务架构(A Macro Services Framework)