【VIJOS - P1037】搭建双塔(dp)
題干:
描述
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 2Copy
樣例輸出1
7Copy
來源
某校NOIP模擬題
解題報告:
非常巧妙的dp題,類似于背包,dp[i][j]表示前i塊木塊,高塊和低塊的差值為j時,最低的木塊的最大高度。(其實維護的是最高的木塊的最大高度也可以)
注意判斷無解是<=0而不是<0。因為一直不選木塊也可以成功轉移到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*/如果要維護最高高度的話就這樣轉移:
總結
以上是生活随笔為你收集整理的【VIJOS - P1037】搭建双塔(dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 办信用卡如何包装 怎么包装申请信用卡
- 下一篇: php version.,PHP_VER