1. 程式人生 > >洛谷·積木城堡

洛谷·積木城堡

【揹包問題】

初見安~這裡是傳送門:洛谷P1504

題目

XC的兒子小XC最喜歡玩的遊戲用積木壘漂亮的城堡。城堡是用一些立方體的積木壘成的,城堡的每一層是一塊積木。小XC是一個比他爸爸XC還聰明的孩子,他發現壘城堡的時候,如果下面的積木比上面的積木大,那麼城堡便不容易倒。所以他在壘城堡的時候總是遵循這樣的規則。

小XC想把自己壘的城堡送給幼兒園裡漂亮的女孩子們,這樣可以增加他的好感度。為了公平起見,他決定把送給每個女孩子一樣高的城堡,這樣可以避免女孩子們為了獲得更漂亮的城堡而引起爭執。可是他發現自己在壘城堡的時候並沒有預先考慮到這一點。所以他現在要改造城堡。由於他沒有多餘的積木了,他靈機一動,想出了一個巧妙的改造方案。他決定從每一個城堡中挪去一些積木,使得最終每座城堡都一樣高。為了使他的城堡更雄偉,他覺得應該使最後的城堡都儘可能的高。

任務:

請你幫助小XC編一個程式,根據他壘的所有城堡的資訊,決定應該移去哪些積木才能獲得最佳的效果。

輸入格式:

第一行是一個整數N(N<=100),表示一共有幾座城堡。以下N行每行是一系列非負整數,用一個空格分隔,按從下往上的順序依次給出一座城堡中所有積木的稜長。用-1結束。一座城堡中的積木不超過100塊,每塊積木的稜長不超過100。

輸出格式:

一個整數,表示最後城堡的最大可能的高度。如果找不到合適的方案,則輸出0。

輸入輸出樣例

輸入樣例:
2
2 1 –1
3 2 1 –1
輸出樣例:
3

題解:

本題要求每個城堡一樣高且儘量高,即求每個城堡都可達到的最大高度,所以可以將這些城堡看做只是分了堆的積木,列舉每個城堡可達到的高度,最後達到的城堡數量正好為n個城堡的最大高度即為所求。

思路看起來很簡單(卡了我一個多小時 ),重點在於:如何列舉每個城堡可以達到的高度?如果全用for迴圈來列舉的話,會比較麻煩,所以——可以用到揹包問題的思路(說白了還是列舉

但從大到小列舉的原因——你們可以手動樣例試一下(懶得解釋 ),一開始是為了避免重複(後來發現避免不了就懶得改了 )。
程式碼如下——

#include<bits/stdc++.h>
using namespace std;
bool dp[30000];
int n;
int a[100];
int ans[100000];
int maxn;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        memset(dp,0,sizeof dp);
        dp[0]=1;
        int t=0,sum=0;
        int x;
        while(666)
        {
            cin>>x;
            if(x<0) break; 
            a[++t]=x;
            sum+=x;
        }

        if(sum>maxn) maxn=sum;
        
        for(int j=1;j<=t;j++)
        {
            for(int k=sum;k>=a[j];k--)
            {
                if(dp[k-a[j]]&&!dp[k])
                {
                    dp[k]=1;
                    ans[k]++;
                }
            }
        }
    }
    
    for(int i=maxn;i>=1;i--)
    {
        if(ans[i]==n)
        {
            cout<<i<<endl;
            return 0;
        }
    }
    cout<<0<<endl;
    return 0;
}

迎評:)
——End——