2018 ccpc秦皇島 Riddle 狀壓dp

2021-09-27 06:22:40 字數 2068 閱讀 6552

拖了一年了才補。。。去年現場賽3個小時沒做出來,今年看了半個小時就有思路了= =

有陣列anan

​其中aiai

​可以作為物品,也可以作為袋子

如果作為物品,aiai

​作為物品的重量,不一定要裝在袋子裡

如果作為袋子,aiai

​作為袋子的容量,必須要裝滿物品。

對每一組輸入,輸出總的方案數

n

<15,

ai

<

2000

n<15,<2000

n<15

,ai​

<20

00乙個合法的最終狀態可以將物品分為幾類:

1.作為物品且沒有放在袋子裡的,即完全沒有考慮的物品

2.作為物品和袋子組成合法袋子

3.作為袋子且裝滿物品

可以用乙個二進位制數表示當前狀態,第i位下標為1表示考慮這個東西(可以作為物品也可以作為狀態),為0表示不考慮這個東西

d p[

sta]

dp[sta]

dp[sta

]表示當前狀態為sta

stast

a時的方案總數.

而乙個合法方案的轉移必定是對於當前sta

stast

a狀態沒有考慮到的東西產生了乙個新的合法的袋子,轉移到了乙個考慮了更多東西的狀態。(新加乙個合法的袋子)

用c nt

[x

]cnt[x]

cnt[x]

表示考慮x狀態的東西作為乙個乙個

乙個合法的袋子的方案數

整個d pdp

dp的轉移過程可以看做是計數01

0101

揹包的轉移過程,先列舉物品,再列舉揹包轉移。注意在列舉揹包的時候一定是當前列舉的乙個合法包的補集的子集,保證物品只會出現在這個合法包中。

設當前考慮的包狀態為i

ii,當前的狀態為j

jj轉移方程如下:

注意不能寫j

>=0

j>=0

j>=0

會死迴圈

#include

using namespace std;

#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

#define ll long long

#define int ll

#define debug cout<<"****"<#define pb push_back

#define endl '\n'

#define fi first

#define se second

#define db double

#define pii pair

#define mp make_pair

const

int mod=

(int

)1e9+7

;const

int maxn=(1

<<15)

;int n,t;

int a[20]

;int sum[maxn+5]

,dp[maxn+5]

;int cnt[maxn+5]

;//第i位為1表示考慮這個數字,為0表示不考慮當前數字

signed

main()

for(

int i=

0;i<(1

<;i++)}

//cnt[i]表示組成當前狀態的乙個揹包

for(

int i=

0;i<(1

<;i++

)//當前的狀態}}

}for

(int i=

0;i<(1

<;i++

)//當前的袋子

} cout<<]<}return0;

}/*33

1 1 1

51 1 2 2 3

101 2 3 4 5 6 7 8 9 10

*//*7 15 127*/

秦皇島2018CCPC現場賽

所有的磨難挫折,都該慶幸,它來的還不算晚.大海我來了 來之前,就聽說這裡有海,很欣喜.畢竟乙個土生土長的山西人,還沒 看過大海.坐了一夜的火車,下車直奔博維酒店,距離比賽地點特別近,步行10分鐘,搞定了報道,然後就回酒店補覺了.下午ge掉了開幕式,在熱身賽開始前,堪堪來到賽場.熱身賽 cqw和xzw...

2018CCPC秦皇島站(賽後總結)

這大概是我的最後一場acm競賽了,我們長途跋涉來到秦皇島參賽,然而表現的一點兒也不好。9.27號的熱身賽共有四道題,熱身賽估計有點難,第二名也就只做了兩題。我們只做出了一道題,不過第二題我們在比賽結束後,和趙老師討論出了這道題的解法,賽場上我們是用迴圈暴力求解的,複雜度是o n 3 o n o n3...

2018ccpc吉林 C JUSTICE 思維

題意 n個物品,每個物品重量1 2 k i 問可不可以分成兩份,讓這兩份的總量都大於1 2 題解 因為兩份都要大於1 2,那麼我們兩份都找出1 2,剩下的就無所謂了。我們把問題轉化為,兩份都需要找到乙個1,因為 1 2 1 4 1 4,所以乙個1等價於兩個2,4個3.我們先從小到大排個序,令cnt1...