描述

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

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

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

格式

輸入格式

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

輸出格式

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

樣例1

樣例輸入1[複製]

2
2 1 –1
3 2 1 –1

樣例輸出1[複製]

3

提示

原資料有誤,不知我修正後是不是對?

來源

NlogN年之前浙江省隊選拔第X輪

本題我用的是方案總數的做法:

Accepted

 
100
247 532 ksq2013 C++ 2016-08-19 11:14:10
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
using namespace std;
int n,e;
bool f0[11111],f1[11111];
int main()
{
scanf("%d",&n);
memset(f0,true,sizeof(f0));
while(n--){
memset(f1,false,sizeof(f1));
f1[0]=true;
while(scanf("%d",&e)&&e!=-1)
for(int i=10000-e;i>=0;i--)
if(f1[i])f1[i+e]=true;
for(int i=10000;i>=0;i--)
f0[i]=f0[i]&f1[i];
}
for(int i=10000;i>=0;i--)
if(f0[i]){
printf("%d\n",i);
break;
}
return 0;
}

還有一種做法,似乎是二分答案,不斷n次01揹包,若n個01揹包都可達到二分值則記錄(這兩個是一個思路吧,只是說起來有不同點)。