程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> vijos 1037 搭建雙塔 簡單DP

vijos 1037 搭建雙塔 簡單DP

編輯:C++入門知識

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”。

 


一看就跟背包有些類似,實際上確實是個很簡單的DP

用dp[i][j] 表示的是前i個水晶,湊成的兩塔高度差為j的較低塔的最大高度。

那麼它的狀態可能由四種情況轉化而來

1.該物品沒用上

2.低塔加上了該物品還是低塔

3.高塔加上了該物品邊的更高了

4.低塔加上了該物品變成了高塔

這裡我們可以畫幾個圖,就清晰許多了

轉移方程請看代碼


[cpp] view plaincopyprint?#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#include <vector>  
#include <queue>  
#include <set>  
#include <stack>  
#include <map>  
#define MAXN 777  
#define MAXM 400005  
#define INF 1000000007  
using namespace std; 
int n; 
int f[111][2222], c[111]; 
int main() 

    scanf("%d", &n); 
    int sum = 0; 
    for(int i = 1; i <= n; i++) 
    { 
        scanf("%d", &c[i]); 
        sum += c[i]; 
    } 
    memset(f, -1, sizeof(f)); 
    f[0][0] = 0; 
    for(int i = 1; i <= n; i++) 
    { 
        for(int j = 0; j <= sum; j++) 
        { 
            if(f[i - 1][j] != -1) f[i][j] = f[i - 1][j]; 
            if(j + c[i] <= sum && f[i - 1][j + c[i]] != -1) 
                f[i][j] = max(f[i][j], f[i - 1][j + c[i]] + c[i]); 
            if(j >= c[i] && f[i - 1][j - c[i]] != -1) 
                f[i][j] = max(f[i][j], f[i - 1][j - c[i]]); 
            if(c[i] > j && f[i - 1][c[i] - j] != -1) 
                f[i][j] = max(f[i][j], f[i - 1][c[i] - j] + c[i] - j); 
        } 
    } 
    if(f[n][0] > 0) printf("%d\n", f[n][0]); 
    else printf("Impossible\n"); 
    return 0; 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#define MAXN 777
#define MAXM 400005
#define INF 1000000007
using namespace std;
int n;
int f[111][2222], c[111];
int main()
{
    scanf("%d", &n);
    int sum = 0;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &c[i]);
        sum += c[i];
    }
    memset(f, -1, sizeof(f));
    f[0][0] = 0;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= sum; j++)
        {
            if(f[i - 1][j] != -1) f[i][j] = f[i - 1][j];
            if(j + c[i] <= sum && f[i - 1][j + c[i]] != -1)
                f[i][j] = max(f[i][j], f[i - 1][j + c[i]] + c[i]);
            if(j >= c[i] && f[i - 1][j - c[i]] != -1)
                f[i][j] = max(f[i][j], f[i - 1][j - c[i]]);
            if(c[i] > j && f[i - 1][c[i] - j] != -1)
                f[i][j] = max(f[i][j], f[i - 1][c[i] - j] + c[i] - j);
        }
    }
    if(f[n][0] > 0) printf("%d\n", f[n][0]);
    else printf("Impossible\n");
    return 0;
}

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved