hdu 4529(状态dp)
生活随笔
收集整理的這篇文章主要介紹了
hdu 4529(状态dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
鄭廠長系列故事——N騎士問題
Time Limit: 6000/3000 MS (Java/Others)????Memory Limit: 65535/32768 K (Java/Others)Problem Description 鄭廠長不是正廠長
也不是副廠長
他根本就不是廠長
還是那個騰訊公司的碼農
一個業余時間喜歡下棋的碼農
最近,鄭廠長對八皇后問題很感興趣,拿著國際象棋研究了好幾天,終于研究透了。興奮之余,坐在棋盤前的他又開始無聊了。無意間,他看見眼前的棋盤上只擺了八個皇后,感覺空蕩蕩的,恰好又發現身邊還有幾個騎士,于是,他想把這些騎士也擺到棋盤上去,當然棋盤上的一個位置只能放一個棋子。因為受八皇后問題的影響,他希望自己把這些騎士擺上去之后,也要滿足每2個騎士之間不能相互攻擊。
現在鄭廠長想知道共有多少種擺法,你能幫助他嗎?
騎士的下法:
每步棋先橫走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外橫走或豎走一格(即走“日”字)??梢栽阶?#xff0c;沒有"中國象棋"的"蹩馬腿"限制。
Input 輸入第一行為一個整數T(1<=T<=8),表示有T組測試數據;
每組數據首先是一個整數N(1<=n<=10),表示要擺N個騎士上去;
接下來是一個8*8的矩陣來描述一個棋盤,’.’表示這個位置是空的,’*’表示這個位置上已經放了皇后了;
數據中的初始棋盤保證是一個合法的八皇后擺法。
Output 對每組數據,請在一行內輸出一個整數,表示合法的方案數。
Sample Input 2 1 *....... ....*... .......* .....*.. ..*..... ......*. .*...... ...*.... 2 *....... ....*... .......* .....*.. ..*..... ......*. .*...... ...*....
Sample Output 56 1409
Source 2013騰訊編程馬拉松初賽第五場(3月25日)?
解題思路:定義狀態dp[i][j][p][q]:表示前i行,使用了j個騎士,第i行的狀態為p,第i-1行的狀態為q的方案數。這是我最開始的想法,但是后來一想時間復雜度會超大,所以就一直不敢去寫,結果看了別人的解題報告,確實是這么思考的,但很詫異居然沒有超時。
AC: #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int t,N; char s[10][10]; bool suit[10][1<<8+5]; int dp[8][11][1<<8][1<<8];//dp[i][j][a][b],第i行,前i行j個騎士,i行狀態a,i-1行狀態b的方案數 int one[1<<8+5]; //處理出每行合法的狀態 inline void init() {memset(suit,0,sizeof(suit));for(int i=0;i<8;i++){for(int j=0;j< 1<<8;j++){int tag=1;for(int k=0;k<8;k++){if(s[i][k]=='*'&&(j&(1<<k))){tag=0; break;}}if(tag) suit[i][j]=1;}} } inline int getOne(int i) {int ans=0;while(i){ans+=i%2;i/=2;}return ans; }int main() {for(int i=0;i<(1<<8);i++)one[i]=getOne(i);scanf("%d",&t);while(t--){scanf("%d",&N);for(int i=0;i<8;i++) scanf("%s",s[i]);init();memset(dp,0,sizeof(dp));for(int i=0;i<(1<<8);i++){if(suit[0][i] && one[i]<=N){dp[0][one[i]][i][0]=1;}}for(int i=1;i<8;i++)for(int n=0;n<=N;n++)for(int j=0;j<(1<<8);j++){if(one[j] > n) continue;if(!suit[i][j]) continue;for(int k=0;k< 1<<8;k++){if(k & (j<<2)) continue;if(k & (j>>2)) continue;for(int r = 0;r < (1<<8);r++){if(r & (j<<1)) continue;if(r & (j>>1)) continue;dp[i][n][j][k]+=dp[i-1][n-one[j]][k][r];}}}int ans=0;for(int i=0;i<(1<<8);i++){if(suit[7][i]){for(int j=0;j<(1<<8);j++){if(suit[6][j])ans+=dp[7][N][i][j];}}}printf("%d\n",ans);} }
總結
以上是生活随笔為你收集整理的hdu 4529(状态dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 2059(dp)
- 下一篇: JEECG 3.7.8 新版表单校验提示