vijos1037搭建雙塔

2022-08-20 06:21:12 字數 3839 閱讀 9884

我好像離上次寫blog有1個月了吧,想想現在太浪了,寫篇題解壓壓驚σ( ° △ °|||)︴。

2023年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」。

5

1 3 4 5 2

7
某校noip模擬題

這題非常有意思,

大暴力肯定是不行的,這裡有明顯的重疊子問題,我們可以試試看動態規劃,

首先,我們確定一下它的最優子結構,

f[i][j][k]表示前i個積木是否能有一塔為j,另一塔為k的情況。

轉移非常好寫(這裡就不寫了),並且我們可以用揹包的思想乾掉一維,

**:

1 #include2 #include3 #include4 #include5 #include6 #include7 #include8

using

namespace

std;

9 typedef long

long

ll;10 typedef long

double

ld;11 typedef pairpr;

12const

double pi=acos(-1

);13

#define rep(i,a,n) for(int i=a;i<=n;i++)

14#define per(i,n,a) for(int i=n;i>=a;i--)

15#define rep(i,u) for(int i=head[u];i;i=next[i])

16#define clr(a) memset(a,0,sizeof(a))

17#define pb push_back

18#define mp make_pair

19#define fi first

20#define sc second

21#define pq priority_queue

22#define pqb priority_queue , less>

23#define pqs priority_queue , greater>

24#define vec vector

25 ld eps=1e-9

;26 ll pp=1000000007

;27 ll mo(ll a,ll pp)

28 ll powmod(ll a,ll b,ll pp)

29void fre()

30//

void add(int x,int y,int z)

31int dx[5]=,dy[5]=;

32 ll read()

37const

int n=2005;38

intf[n][n],a[n],sum;

39int

main()

4048

for (int i=sum;i>=1;i--)

49if

(f[i][i])

53 printf("

impossible");

54return0;

55 }

view code

時間複雜度:sum^2*n;

肯定是過不了的,但資料水一不小心就過了(霧)。

想到這裡我們有沒有感覺最後一位只存0/1有點浪費。

於是乎,

f[i][j]表示前i個積木一塔為j的離他最近的塔的高度。

可是很氣的是這不是乙個最優子結構,(反例自己找),

陷入了沉思,

用一塔的高度做狀態不行,那差呢》?

f[i][j]表示前i個積木差為i的最矮的塔高。

試試看轉移:

f[i][j]=max(f[i][j],f[i-1][j]);

f[i][j]=max(f[i][j],f[i-1][j+a[i]]+a[i]);

if (j>=a[i]) f[i][j]=max(f[i][j],f[i-1][j-a[i]]);

else f[i][j]=max(f[i][j],f[i-1][a[i]-j]+a[i]-j);

非常好,就有滿足了條件,

**:

1 #include2 #include3 #include4 #include5 #include6 #include7 #include8

using

namespace

std;

9 typedef long

long

ll;10 typedef long

double

ld;11 typedef pairpr;

12const

double pi=acos(-1

);13

#define rep(i,a,n) for(int i=a;i<=n;i++)

14#define per(i,n,a) for(int i=n;i>=a;i--)

15#define rep(i,u) for(int i=head[u];i;i=next[i])

16#define clr(a) memset(a,0,sizeof(a))

17#define pb push_back

18#define mp make_pair

19#define fi first

20#define sc second

21#define pq priority_queue

22#define pqb priority_queue , less>

23#define pqs priority_queue , greater>

24#define vec vector

25 ld eps=1e-9

;26 ll pp=1000000007

;27 ll mo(ll a,ll pp)

28 ll powmod(ll a,ll b,ll pp)

29void fre()

30//

void add(int x,int y,int z)

31int dx[5]=,dy[5]=;

32 ll read()

37int n,a[101],f[101][2001

],h;

38int

main()

3956

if (f[n][0]<=0

)57 printf("

%s","

impossible");

58else

59 printf("

%d\n

",f[n][0

]);60 }

view code

終於這道題完美的解決了。

搭建雙塔(Vijos 1037)

2001年9月11日,一場突發的災難將紐約世界 中心大廈夷為平地,mr.f曾親眼目睹了這次災難。為了紀念 9?11 事件,mr.f決定自己用水晶來搭建一座雙塔。mr.f有n塊水晶,每塊水晶有乙個高度,他想用這n塊水晶搭建兩座有同樣高度的塔,使他們成為一座雙塔,mr.f可以從這n塊水晶中任取m 1 m...

vijos1037 搭建雙塔

題目 限制和答案,到底哪乙個應該是陣列下標 設f i j 為取到第i個水晶,高度差為j時的較高塔的最高高度 那答案的更新,分方和不放討論 一 不放,dp i j dp i 1 j 二 放 放的話,對答案影響有三種情況 1 放在較高塔上,dp i j dp i j h i h i 高度差增加h i 高...

搭建雙塔(vijos 1037)

2001年9月11日,一場突發的災難將紐約世界 中心大廈夷為平地,mr.f曾親眼目睹了這次災難。為了紀念 9?11 事件,mr.f決定自己用水晶來搭建一座雙塔。mr.f有n塊水晶,每塊水晶有乙個高度,他想用這n塊水晶搭建兩座有同樣高度的塔,使他們成為一座雙塔,mr.f可以從這n塊水晶中任取m 1 m...