【VIJOS - P1037】搭建双塔(dp)
題干:
描述
2001年9月11日,一場(chǎng)突發(fā)的災(zāi)難將紐約世界貿(mào)易中心大廈夷為平地,Mr. F曾親眼目睹了這次災(zāi)難。為了紀(jì)念“9?11”事件,Mr. F決定自己用水晶來搭建一座雙塔。
Mr. F有N塊水晶,每塊水晶有一個(gè)高度,他想用這N塊水晶搭建兩座有同樣高度的塔,使他們成為一座雙塔,Mr. F可以從這N塊水晶中任取M(1≤M≤N)塊來搭建。但是他不知道能否使兩座塔有同樣的高度,也不知道如果能搭建成一座雙塔,這座雙塔的最大高度是多少。所以他來請(qǐng)你幫忙。
給定水晶的數(shù)量N(1≤N≤100)和每塊水晶的高度Hi(N塊水晶高度的總和不超過2000),你的任務(wù)是判斷Mr. F能否用這些水晶搭建成一座雙塔(兩座塔有同樣的高度),如果能,則輸出所能搭建的雙塔的最大高度,否則輸出“Impossible”。
格式
輸入格式
輸入的第一行為一個(gè)數(shù)N,表示水晶的數(shù)量。第二行為N個(gè)數(shù),第i個(gè)數(shù)表示第i個(gè)水晶的高度。
輸出格式
輸出僅包含一行,如果能搭成一座雙塔,則輸出雙塔的最大高度,否則輸出一個(gè)字符串“Impossible”。
樣例1
樣例輸入1
5 1 3 4 5 2Copy
樣例輸出1
7Copy
來源
某校NOIP模擬題
解題報(bào)告:
非常巧妙的dp題,類似于背包,dp[i][j]表示前i塊木塊,高塊和低塊的差值為j時(shí),最低的木塊的最大高度。(其實(shí)維護(hù)的是最高的木塊的最大高度也可以)
注意判斷無解是<=0而不是<0。因?yàn)橐恢辈贿x木塊也可以成功轉(zhuǎn)移到dp[n][0]只是值為0)。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<stack> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int INF = 0x3f3f3f3f; const int MAX = 100 + 5; int n; int dp[MAX][5555]; int a[MAX]; int main() {cin>>n;memset(dp,-INF,sizeof dp);dp[0][0] = 0;for(int i = 1; i<=n; i++) cin>>a[i];for(int i = 1; i<=n; i++) {for(int j = 0; j<=2004; j++) { dp[i][j] = max(dp[i][j],dp[i-1][j]);//第i塊磚不放if(j>=a[i])dp[i][j] = max(dp[i][j],dp[i-1][j-a[i]]);//放在高的上 dp[i][j] = max(dp[i][j],dp[i-1][j+a[i]]+a[i]);//放在矮的上且沒超過高塔if(a[i]>=j)dp[i][j] = max(dp[i][j],dp[i-1][a[i]-j]+(a[i]-j));}}int ans = dp[n][0];if(ans > 0) printf("%d\n",ans);else printf("Impossible\n");return 0 ; } /* 2 1 3*/如果要維護(hù)最高高度的話就這樣轉(zhuǎn)移:
總結(jié)
以上是生活随笔為你收集整理的【VIJOS - P1037】搭建双塔(dp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 办信用卡如何包装 怎么包装申请信用卡
- 下一篇: 【PAT - 甲级1012】The Be