題意:有x*y的矩陣塊,問能否把該矩陣切成n塊大小分別為a0,a1,a(n-1的小塊。每一刀切到底。
解題分析:
現在我們有任意a*b(a
a. 如果x = 1,那麼可以將矩陣塊切成x個小塊。
b .否則我們切一刀把矩陣塊分成兩個子塊即把x個小塊分成x0和x1塊。
我們利用狀態壓縮的方法,定義這x塊分別為s的二進位制為1處表示的矩陣塊(在輸入時,矩陣塊是有順序的)那麼s1 = s^s0.)(x為s的二進位制中1的個數)
(我們定義這x塊大小的總和為sum[s],則sum[s] =sum[s0]+sum[s1],同時
a*b的矩陣塊這一條件可以等價為,短邊為
a,矩陣塊大小為
sum[s]
,另一邊
b=sum[s]/a)
則可以將a*b的矩陣塊切成x塊條件是:
對於所有的s0,
s1:(即x為s的所有子集,s1為s0對s的補集)
1) sum[s0]%a == 0(x塊可以通過切b邊分成x0和x1塊)&&(一邊為
a,總和為
sum[s0]
的矩陣塊可以切成
x0塊)&&(一邊為
a,總和為
sum[s1]
的矩陣塊可以切成
x1塊)
2) 或者sum[s0]%b== 0(x塊可以通過切a邊分成x0和x1塊)&&(一邊為
b,總和為
sum[s0]
的矩陣塊可以切成
x0塊)&&(一邊為
b總和為
sum[s1]
的矩陣塊可以切成
x1塊)
如果都不滿足,則不能滿足條件。
因為會多次詢問子問題(一邊為
a,總和為
sum[s0]
的矩陣塊可以切成
x0塊),通過記憶化搜尋的方法降低複雜度。
具體**如下:
#includeusing namespace std;
const int maxn = 17;
int a[maxn];
int sum[1<>1)+(x&1);
}int count_bit(int x)
return cnt;
}int dfs(int s,int x)
return dp[s][x] = 0;
}int main(){
int n;
int ca = 1;
while(cin>>n&&n){
int x,y;
cin>>x>>y;
memset(sum,0,sizeof(sum));
for(int i =0;i>a[i];
for(int s = 1;s<(1<
UVa 10944 狀態壓縮DP
第一道狀態壓縮dp題,感覺要好好學習這種思維方式 首先設l的位置為 pointx 0 pointy 0 其他節點的位置為 pointx i pointy i 然後求出各個節點之間的距離dis i j max 我們用乙個n位2進製數 bn 1,b0 表示堅果收集情況的組合狀態 其中bi 0表示第i 1...
UVA 6625 狀態壓縮dp
這個題目的意思是給定k,n k,n 7 並給定k行每行有幾個連續的空格,所有的行左對齊,每一行最多7個,下面的行的空格數 上面相鄰行的空格數 給定乙個填數字的規則,當對於任意位置i,j num i j num i 1 j num i j num i j 1 問有 只用數字1 n 有多少種填滿空格的方...
uva11795 簡單狀態壓縮DP
一看到n 16就想到狀態壓縮dp了,而且只要儲存這個狀態就行了 轉移時也用狀態壓縮的轉移方法,比較兩個二進位制數,就能知道能否從已知狀態轉移到需要的狀態 開始沒看到題目給的就是二進位制數,自己還轉換成了二進位制 還有要記得用longlong 不能因為這個wa 還有位運算還不是很熟悉,可以用異或來去掉...