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

洛谷P1504 積木城堡

一次 sin 順序 從大到小 pre 既然 積木 一點 題目

題目描述

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

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

任務:

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

輸入輸出格式

輸入格式:

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

輸出格式:

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

輸入輸出樣例

輸入樣例#1:
2
2 1 –1
3 2 1 –1
輸出樣例#1:
3
分析:一開始看錯題目了,以為只能抽掉最上面一根,我就把最高的那個城堡找出來,然後不斷移去最上面那個積木,看能不能達到要求,光榮WA.
既然可以隨便抽積木,那麽我們記錄每一個城堡能達到的高度就好了,因為每個積木只能用一次,那麽相當於0/1背包,用bool記錄就好了.接下來從大到小枚舉高度,看能不能符合要求就好了.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int f[110][110];
bool can[110][10010];

int n,tot,cnt,cc,ccnt,maxn;

int main()
{
    scanf("%d",&n);
    for (int i = 1; i <= n; i++)
    can[i][0] = 1
; for (int i = 1; i <= n; i++) { int t; tot = 0; cnt = 0; while (scanf("%d",&t) && t != -1) { f[i][++cnt] = t; tot += t; } if (tot > maxn) maxn = tot; for (int j = 1; j <= cnt; j++) for (int k = tot; k >= 1; k--) if (k - f[i][j] >= 0) { if (can[i][k - f[i][j]]) can[i][k] = 1; } } for (int i = maxn; i >= 1; i--) { cnt = 0; for (int j = 1; j <= n; j++) { if (can[j][i]) cnt++; } if (cnt == n) { printf("%d\n",i); return 0; } } printf("0\n"); return 0; }

 

洛谷P1504 積木城堡