hdu 5180 状态压缩 dp 打表
题意:
在n*n的国际象棋中,放置若干个国王和k个车,使得国王之间不互相攻击,车之间不互相攻击,车不可攻击到国王(这并不代表国王不能攻击到车)。国王能攻击到它上下左右,左上左下右上右下八个位置的棋子,车可以攻击到同一行或同一列中的棋子,求方案总数对1000000007取模后的值。
限制:
1 <= n <=15; 0 <= k <=15
思路:
状态压缩,dp,打表套打表
打表程序如下:
打表程序1:
tab[a][b]表示a*b的棋盘王的放置情况的种数。
由于只有15*15,所以可以用状态压缩dp来解决。
题意:
在n*n的国际象棋中,放置若干个国王和k个车,使得国王之间不互相攻击,车之间不互相攻击,车不可攻击到国王(这并不代表国王不能攻击到车)。国王能攻击到它上下左右,左上左下右上右下八个位置的棋子,车可以攻击到同一行或同一列中的棋子,求方案总数对1000000007取模后的值。
限制:
1 <= n <=15; 0 <= k <=15
思路:
状态压缩,dp,打表套打表
/*hdu 5180
题意:
在n*n的国际象棋中,放置若干个国王和k个车,使得国王之间不互相攻击,车之间不互相攻击,车不可攻击到国王(这并不代表国王不能攻击到车)。国王能攻击到它上下左右,左上左下右上右下八个位置的棋子,车可以攻击到同一行或同一列中的棋子,求方案总数对1000000007取模后的值。
限制:
1 <= n <=15; 0 <= k <=15
思路:
状态压缩,dp,打表套打表
*/
#include
#include
using namespace std;
int ans[15][16]={
2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
5,8,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
35,72,36,6,0,0,0,0,0,0,0,0,0,0,0,0,
314,940,702,192,24,0,0,0,0,0,0,0,0,0,0,0,
6427,20953,18778,6528,1200,120,0,0,0,0,0,0,0,0,0,0,
202841,724224,766278,310368,63000,8640,720,0,0,0,0,0,0,0,0,0,
12727570,45687569,51049098,22486656,4751400,648000,70560,5040,0,0,0,0,0,0,0,0,
355115594,736342192,480159099,593158322,564699600,71527200,7161840,645120,40320,0,0,0,0,0,0,0,
718817248,766062498,551790315,804772379,958725252,916206996,91739593,85155840,6531840,362880,0,0,0,0,0,0,
789281595,29367309,234810099,689850602,160354814,575223606,565338593,166965641,87551353,72576000,3628800,0,0,0,0,0,
245046738,212490784,527909966,404618207,648188905,539918379,532542087,165451585,428944600,878079902,878169600,39916800,0,0,0,0,
681555006,278546674,315035573,624869750,794507062,84429000,792648481,661448548,160683200,93278547,346974481,496038323,479001600,0,0,0,
413451720,259920010,496775457,225920769,842092390,332550368,221710589,232620660,166171087,462729811,955852083,835265947,902539673,227020758,0,0,
571703274,654602013,270251289,900887757,942422378,974702258,610771898,46596778,844659211,467836761,298284961,960033762,424915175,992136520,178290591,0,
7017421,361818480,635021015,633194321,924790619,16861446,556906023,606568231,432184532,717658304,181068670,990596447,108561136,862468715,230765390,674358851};
int main(){
int T;
int n,k;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
printf("%d\n",ans[n-1][k]);
}
return 0;
}
打表程序如下:
打表程序1:
tab[a][b]表示a*b的棋盘王的放置情况的种数。
由于只有15*15,所以可以用状态压缩dp来解决。
/*hdu 5180
表1:
tab[a][b]表示a*b的棋盘王的放置情况的种数。
由于只有15*15,所以可以用状态压缩dp来解决。
*/
#include
#include
#include
using namespace std;
#define LL __int64
const int MOD=1000000007;
LL dp[20][1<<16];
int a[1<<16],cnt;
int tab[20][20];
int main(){
for(int i=1;i<=15;++i){
cnt=0;
for(int j=0;j<(1<
>1))) continue;
dp[j][a[k]]=(dp[j][a[k]]+dp[j-1][a[l]])%MOD;
}
sum=(sum+dp[j][a[k]])%MOD;
}
tab[j+1][i]=sum;
}
}
for(int i=0;i<=15;++i){
for(int j=0;j<=15;++j)
cout<
<<','; cout<
打表程序2:
基于表1然后打出表2,
表2是答案表。
因为问题只有15*16,对于每种情况:(n,k),先之间考虑k辆车的情况,可以用两个二进制数表示k辆车在棋盘上的分布,然后可以发现车的本质是把棋盘分割成若干部分,每部分的王的放置情况在表1中已经打出,剩下的部分可以很容易算出来。
ps:这个程序一定要好好优化,不然要打好长时间,我的大概要跑10min左右。
/*hdu 5180
表2:
基于表1然后打出表2,
表2是答案表。
因为问题只有15*16,对于每种情况:(n,k),先之间考虑k辆车的情况,可以用两个二进制数表示k辆车在棋盘上的分布,然后可以发现车的本质是把棋盘分割成若干部分,每部分的王的放置情况在表1中已经打出,剩下的部分可以很容易算出来。
*/
#include
#include
#include