生活随笔
收集整理的這篇文章主要介紹了
1592 国王
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1592 國王
練習狀壓DP…
求使它們無法互相攻擊的方案總數(shù),動態(tài)規(guī)劃,其實和dfs有點像,類似于n皇后問題
n<=10,數(shù)據(jù)范圍真的是可以了,但是深搜的話,時間復雜度會指數(shù)爆炸一樣,不要想了
因為對于每一個格子都有放或者不放兩種情況,那么就可以用二進制來來優(yōu)化
那么一行的數(shù)據(jù)就濃縮成一個數(shù)了
怎么設計狀態(tài)?
我們要在n×n的棋盤放k個國王,那么就用f[i][j][k]表示第i行狀態(tài)是a[j],目前放了k個棋子
f[i][j][k]=sum{ i-1,l,k-num[j] }其中l(wèi)枚舉上一行狀態(tài)的變量,num[j]是a[j]是這個狀態(tài)可以放置國王數(shù)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std
;
typedef long long ll
;
ll n
,k
;
ll num
[1000];
ll a
[1000];
ll f
[300][300][300];
ll ans
;
ll sum
;
void sol()
{int cnt
=0;for(int i
=0;i
<(1<<n
);i
++){if( i
&(i
<<1) ) continue;cnt
=0;for(int j
=0;j
<n
;j
++) if((1<<j
)&i
) cnt
++;a
[++sum
]=i
; num
[sum
]=cnt
;}
}
void dp()
{f
[0][1][0]=1;for(int i
=1;i
<=n
;i
++)for(int j
=1;j
<=sum
;j
++)for(int kk
=0;kk
<=k
;kk
++){if(kk
>=num
[j
])for(int l
=1;l
<=sum
;l
++)if(!(a
[l
]&a
[j
]) && !(a
[l
]&(a
[j
]<<1)) && !(a
[l
]&(a
[j
]>>1)))f
[i
][j
][kk
]+=f
[i
-1][l
][kk
-num
[j
]]; }for(int i
=1;i
<=sum
;i
++) ans
+=f
[n
][i
][k
];cout
<<ans
<<endl
;
}
int main()
{cin
>>n
>>k
;sol();dp();return 0;
}
總結
以上是生活随笔為你收集整理的1592 国王的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。