《GMOJ Senior 2679 跨時代》題解

2021-09-25 02:42:13 字數 3806 閱讀 9142

給出n

nn根欄杆的長度,讓你從這n

nn根欄杆中選出一些欄杆圍成乙個矩形(必須要剛好圍成乙個矩形,即不能出現多餘的邊長,且不能切斷欄杆,但所給欄杆不一定要全部用上),求圍成矩形的最大面積。

對於30

%30\%

30%的資料,1≤n

≤10

1 \leq n \leq 10

1≤n≤10

;對於100

%100\%

100%

的資料,1≤n

≤16

1 \leq n \leq 16

1≤n≤16

,1

≤欄杆的長度≤15

1 \leq \text \leq 15

1≤欄杆的長度≤1

5。這是一道狀態壓縮動態規劃(狀壓dpdp

dp)題。30分

對於30

%30\%

30%的資料,我們可以用暴力求出。設圍成的矩形的四條邊分別為e1,

e2,e

3,e4

e_1,e_2,e_3,e_4

e1​,e2

​,e3

​,e4

​,那麼在dfs

dfsdf

s時列舉每條邊的每種情況(加入e

1e_1

e1​或e

2e_2

e2​或e

3e_3

e3​或e

4e_4

e4​),最後判斷矩形的長寬是否相等,如果相等就更新答案。**如下:

#

include

intmax

(int x,

int y)

//最大值函式

return y;

}int n,a[22]

;int

dfs(

int s/*列舉的欄杆的編號*/

,int e1/*矩形的第一條長*/

,int e2/*矩形的第二條長*/

,int e3/*矩形的第一條寬*/

,int e4/*矩形的第二條寬*/

)return0;

}return

max(

max(

max(

dfs(s+

1,e1+a[s]

,e2,e3,e4)

,//加入e1

dfs(s+

1,e1,e2+a[s]

,e3,e4)),

//加入e2

max(

dfs(s+

1,e1,e2,e3+a[s]

,e4)

,//加入e3

dfs(s+

1,e1,e2,e3,e4+a[s]))

),//加入e4

dfs(s+

1,e1,e2,e3,e4));

//不選

}int

main()

int t=

dfs(1,

0,0,

0,0)

;//dfs

if(t==0)

//如果無解

else

return0;

}

這樣的時間複雜度為o(5

n)

o(5^n)

o(5n

),100

%100\%

100%

的資料肯定過不了,於是我們考慮對其優化。

100分

因為我們知道矩形的長、寬相等,所以我們設它的長為a

aa,寬為b

bb,深蒐時每根欄杆的情況就由5

55種降到了3

33種:加入a

aa,加入b

bb,不選。最後我們再判斷a

aa,b

bb是否可以分成相等的兩部分,如果可以更新答案即可。

如何判斷a

aa,b

bb是否可以分成相等的兩部分呢?我們用f

ff陣列來判斷。f

if_i

fi​(i

ii為乙個01

0101

串)表示對於i

ii這種選擇欄杆的情況中,選出的欄杆能否分成相等的兩段。因為i

ii是乙個01

0101

串,所以我們可以把它壓縮成乙個十進位制數儲存。

對於每個i

ii,我們先求出選出的欄杆的長度總和sum

sumsu

m。如果sum

sumsu

m是奇數,那麼顯然fi=

fals

ef_i=false

fi​=fa

lse。否則我們用01

0101

不帶權揹包g

gg輔助處理。我們把選出的欄杆逐個放入g

gg中,然後判斷gsu

m÷2g_

gsum÷2

​(一半)能否被組合,若能,表示sum

−sum

÷2

sum-sum \div 2

sum−su

m÷2(即另一半)也能被組合,fi=

true

f_i=true

fi​=tr

ue;否則,fi=

fals

ef_i=false

fi​=fa

lse。

根據以上思路,我們可以打出如下**:

#

include

bool f[

1<<16]

,g[242];

int n,l[22]

;int

max(

int x,

int y)

//最大值函式

return y;

}int

dfs(

int s/*列舉的欄杆的編號*/

,int a/*長的選擇情況*/

,int suma/*兩條長的總和*/

,int b/*寬的選擇情況*/

,int sumb/*兩條寬的總和*/

)return0;

}return

max(

max(

dfs(s+

1,a+(1

<<

(s-1))

,suma+l[s]

,b,sumb)

/*加入長*/

,dfs

(s+1

,a,suma,b+(1

<<

(s-1))

,sumb+l[s]))

/*加入寬*/

,dfs

(s+1

,a,suma,b,sumb)

/*不選*/);

}int

main()

int m=

1

int i=

0;i)//列舉每種情況}if

(sum%2!=

0)//如果長度除以2不是整數(無法平均分成相等的兩個整數部分)

else

for(

int j=

1;j<=n;j++

)//列舉每一條邊}}

f[i]

=g[sum/2]

;//判斷能否被分成相等的兩部分}}

int t=

dfs(1,

0,0,

0,0)

;//dfs

if(t==0)

//如果無解

else

return0;

}

在做像這樣的狀壓dpdp

dp題時,可以先打出暴力,然後再嘗試對其優化。

DP專題 2679 跨時代

1.題目描述 鐘逆時針而繞,噁物猙獰的傾巢,我謙卑安靜地於城堡下的晚禱,壓抑遠古流竄的蠻荒暗號,而管風琴鍵高傲的說,那只是在徒勞。我的樂器在環繞,時代無法淘汰我霸氣的皇朝。你無法預言,因為我越險,翅越豔 沒有句點,跨時代蔓延,翼朝天。月下浮雕,魔鬼的淺笑,狼迎風嚎,蝠翔似黑潮,用孤獨去調尊嚴的色調。...

JZOJ 2679 跨時代 dfs 狀壓

傳送門 有n nn個棍子,要求我們用這些棍子可以拼出的矩形的最大面積 棍子可以不全用 因為n nn很小,又涉及到方案,我們便開始嘗試用狀壓來表示方案 用d fs dfsdf s來列舉棍子是否使用,憑藉前面狀壓表示出來的方案判斷是否可行,不斷取最大值 include include include i...

jzoj2679 跨時代 揹包,dfs,狀壓

若干根棍子,不能折,不能多餘求能夠組成的最大長方形。首先我們發現如果棍子集合s ss長度為l ll且它有子集g gg長度為l 2 frac 2l 那麼就表示這個集合的棍子可以作為乙個矩形的對應兩邊,這樣我們只要列舉兩個不相交集合作為長寬就好了。我們設g ig i gi 表示二進位制表示的集合i ii...