FOJ 195. N Rook Problem

競程作業,2017 交大年度賽 Problem K:FOJ-195

DP 題,他要問說如果有障礙物的話,在 N x N 的棋盤上擺 N 個城堡有幾種擺法

這題我跟本就想不到 QQ
後來是某土木系游泳的時候想到解法告訴我的

就是要一層一層 D 上去,然後我就忘了
以後想到再補

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<iostream>
#include<string.h>
#include<math.h>
#include<bitset>
#define ll unsigned long long int
using namespace std;
bool M[22][22] = {};
ll ji[1048579] = {};
bool isji[1048579] = {};
int n, m;
int BitCount(ll u){
ll uCount;
uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
}
ll dp(ll state){
if(isji[state]){
return ji[state];
}
ll temp = state;
ll tmp = state;
int wei = 1, ge;
while(tmp = tmp>>1){
wei++;
}
ge = BitCount(state);
if(ge==1&&!M[wei][1]){
isji[state] = 1;
return ji[state] = 1;
}
for(int i=0; i<wei; i++){
if(temp%2&&!M[i+1][ge]){
// cout<<i+1<<" "<<ge<<endl;
ji[state] += dp(state-(1<<i));;
}
temp = temp >> 1;
}
isji[state] = 1;
return ji[state];
}
int main(){
int t;
cin>>t;
while(t--){
int x, y;
cin>>n>>m;
memset(M, 0, sizeof(M));
memset(ji, 0, sizeof(ji));
memset(isji, 0, sizeof(isji));
for(int i=0; i<m; i++){
cin>>x>>y;
M[x][y] = 1;
}
ll ans = dp((1 << n)-1);
cout<<ans<<"\n";
// for(int i=1; i<=1<<n; i++)cout<<ji[i]<<" ";
}
}