poj 3254corn fields
題意:
一塊n*m的田,1表示這個地方可以種植,0代表這個地方不能種植。植物種植還必須滿足兩株植物不能相鄰(橫豎都不行)。問共有幾種種植方法,而且當什麼都不種時認為是一種方法。
解題思路:
種植用1表示,不種植用0表示。每一行的情況就可以用乙個二進位制數state來儲存。state的範圍是 [0 ~ 1<< state).
dp[i][state]表示第i行狀態為state的情況下滿足條件的數目。
狀態轉移方程為:dp[i][state] += dp[i-1][pre_state];這個state和pre_state必須滿足意義所給的條件,即左右不相鄰,上下不相鄰。那麼 第i行狀態為state的情況為第i-1行所有滿足條件的狀態為pre_state相加而成。
最後的答案為最後一行所有狀態的情況和相加而得。
位運算需要注意的地方:1.注意打括號
2. 1 & (state>>i) 和 state & ( 1<< i ) 還是有差別的。 前者的答案只有0和1,而後者的答案有0和可能的正數。判斷的時候還是要注意下寫法
3. 當前行是否相鄰的判斷條件是: state & (state<<1) 是否為 0
4. 上下兩行是否相鄰的判斷條件是: state & pre_state 是否為 0
#include
#include
#include
#include
using
namespace
std;
int dp[15][1
<<15];
bool is[15][15];
int n,m;
const
int mod = 1e8;
bool check(int x,int state)
}return
true;
}int main()
}if(i==n) ans = (ans + dp[i][j]) % mod;}}
printf("%lld\n",ans);
}return
0;}
poj 1185炮兵陣地
解題思路:
三維dp陣列來表示狀態的轉移。
dp[i][j][k]表示在第i行狀態為j且第x-1行狀態為k時的方案數。因為第i行放炮兵與第i-1行和i-2行相關。
這裡有個優化:對於每一行的狀態都有 1< < m 種可能,如果每個列舉會tle。其實每一行的最多狀態數也只有60種。因為m最大為10,且每3個不能相鄰,可列舉出來這60種情況。
#include
#include
#include
#include
#include
using
namespace
std;
bool is[150][15];
int dp[110][1
<<11][1
<<11];
int n,m,t=0;
int can[150];
void init()
return;
}int check(int x,int state)
}return cnt;
}int main()
int ans = 0,now;
for(int i=1;i<=n;i++)}}
dp[i][can[j]][can[k]] += now;
if(i==n) ans = max(ans,dp[i][can[j]][can[k]]);}}
}}
printf("%d\n",ans);
return
0;}
poj 3311 hie with the pie
題意:
乙個送外賣的人,要將外賣全部送去所有地點再回到店離,求最短路。
解題思路:
旅行商問題。先用floyed得到每兩個點之間的距離,然後狀壓dp解決旅行商問題。
類似題目:
#include
#include
#include
#include
using
namespace
std;
int path[15][15];
const
int inf = 0x3f3f3f;
int dp[15][1
<<15];
int n;
void floyed()
int main()}}
}int ans = inf;
for(int i=2;i<=n;i++)
cout
0;}
codeforce 580d kefa and dishes
題意:
有n盤菜,每盤菜都有乙個美味值。但是你只能選m盤菜。並且這些吃菜的順序能影響總美味值。如果i當且僅當在j之前吃,那麼會額外加一些美味值,這樣的組合有k組。求選m盤菜吃能獲得的最大的美味值。
解題思路:
dp[i][sta] 表示當前吃的菜是i,狀態為sta的情況。
更新總答案的時候在更新sta的時候可以獲得。
#include
using
namespace
std;
typedef
long
long ll;
ll dp[20][1
<<18];
ll wei[20];
ll add[20][20];
int n,m,k;
bool check(int sta)
if( now == m) return
true;
return
false;
}int main()
memset(dp,0,sizeof(dp));
ll ans = 0;
for(int i = 1; i<(1
for(int k = 1;k<=n;k++)}}
}}
cout
0;}
狀壓DP入門題
學習狀壓之前必須要熟練掌握位運算 位運算名 符號效果 and 按位與如果兩個相應的二進位制位都為1,則該位的結果值為1,否則為0 l or 按位或兩個相應的二進位制位中只要有乙個為1,該位的結果值為1 xor 按位異或 單身狗操作 若參加運算的兩個二進位制位值相同則為0,否則為1 取反 一元運算子,...
狀壓DP入門
洛谷題號p1896 在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。題解 首先暴搜可肯定是超時的所以我門考慮狀壓 因為每個數都可以用二進位制表示出來 二進位制中01可以表示當前行放的棋子的位置 以及...
狀壓DP入門
首發於摸魚世界 狀壓dp,即狀態壓縮dp,它的精髓在於把dp過程中的乙個 狀態 用乙個二進位制數巧妙的表示出來。接下來就從一些入門的狀壓題目來感受一下狀壓的魅力吧 洛谷p5911 poi2004 prz 大致題意 n 個人過最大承載 w 重量的橋,每個人有重量 w i 與過橋時間 t i 多人一組時...