狀態壓縮的想法就是用乙個數代表一組數,以降低表示狀態所代表的維數。
☝一道入門題目
題意:有一片可以放牧的地方n*m(n,m均小於12),然後有的方格上可以種草(1),有的不可以(0),問有多少種可以放牛的方式,一頭牛也不放也可以,其中要求牛不能相互打架(即有公共邊的格仔不能都放上牛),我們就用乙個數字來代替一行的狀態,比如一行最多有12個格仔,那麼就是1<<12(1*2的12次方=4096)個狀態,其中要保證每一行的不打架(①),那麼在放下一行的時候只要保證下一行和它的上一行不打架就可以了(②)。
dp【i】【j】的意思就是第i行狀態為j的時候可行的方案,那麼dp【i】【j】就要等於上一行每個狀態下可行的方案。
①:這個其實就是乙個二進數,其中0和1的是間隔開的,那麼辦法就是把這個數字左移一下,然後再與該數字取&,這樣如果結果是0,就表示這個數字的0和1剛好不會重合
void init()
//cout/經過測試,如果是12位的話,符合狀態的tot數為300左右
}
②這個是要分開考慮的,第一行和剩下的所有行的要求是不同的,因為第一行不需要考慮是否會和前一行打架的因素,在輸入這個是否可以放牧的地圖的時候就會有乙個states函式,把這個每一行當做乙個二進位制數給存起來,這樣在考慮第一行的時候,只需要考慮每個不會打架的狀態是否可以和states相容即可
for(int i=0;i
i++)
然後再考慮其他行
for(int i=1;ifor(int j=0;jif((row[i]&states[j])==states[j])//可不可以採取這個狀態}}
}
ac**
#include
using
namespace
std;
const
int mod=100000000;
#include
int n,m;
int dp[13][1
<<12],row[15],tot,states[1
<<12];
//第i行狀態為j的總的方案個數
void init()
//cout
int main()
}init();
memset(dp,0,sizeof(dp));
for(int i=0;iif((row[0]&states[i])==states[i])
dp[0][i]=1;
}for(int i=1;ifor(int j=0;jif((row[i]&states[j])==states[j])}}
}for(int i=0;i1][i])%mod;
printf("%d\n",ans);
} return
0;}
這道題目主要就是用乙個數字來儲存了一行的狀態就是我們的狀態壓縮,然後每一行都是根據上一行來的,就是我們的 POJ 3254 (狀態壓縮DP)
思路 狀態壓縮dp,用二進位制位的1表示放了,0表示沒有放。設dp i j 表示第i行狀態為j時,前i行的方案數,狀態轉移方程就是 dp i j dp i 1 k j與k這兩個狀態不衝突。最後答案就是dp n 1.top 之和。include include include include incl...
poj3254 狀態壓縮DP
全程精講 農夫有一塊地,被劃分為m行n列大小相等的格仔,其中一些格仔是可以放牧的 用1標記 農夫可以在這些格仔裡放牛,其他格仔則不能放牛 用0標記 並且要求不可以使相鄰格仔都有牛。求方案數 include include using namespace std define mod 10000000...
poj3254 狀態壓縮dp
題意 乙個n m的矩陣,每個格仔是0或者1,1表示土壤肥沃可以種植草地,0則不可以。在種草地的格仔可以放牛,但邊相鄰的兩個格仔不允許同時放牛,問總共有多少種放牛的方案 不放牛也算一種情況 思路 狀態壓縮 感覺不大像dp。dp i j 表示第i行狀態為j時符合條件的方案數 我們可以先求出一行的所有可行...