题目大意:
一个
n∗n
的棋盘,放入
k
个棋子,两两不相邻(
分析:
就是一个简单的
DP
,
f[i][j][k]
表示第
i
行放了
AC code:
#include <cstdio>
#include <cstring>
#include <iostream>
typedef long long LL;
#define get(s, i) ((s>>(i-1))&1)
#define ONLINE_JUDGE
const int MAXN = 10, MAXK = 109;
int n, k;
int sta[1<<MAXN], tot, Map[1<<MAXN];
LL f[2][MAXK][1<<MAXN];
LL ans;
void dfs(int g, int s, int now, int fl, int sum)
{
if(now == n+1)
{
for(int i = 0; i+sum <= k; ++i)
f[fl][i+sum][Map[s]] += f[fl^1][i][Map[g]];
return ;
}
dfs(g, s, now+1, fl, sum);
if(now > 1 && (get(s, now-1) || get(g, now-1))) return ;
if(get(g, now)) return ;
if(now < n && get(g, now+1)) return ;
if(sum+1 > k) return ;
dfs(g, s|(1<<(now-1)), now+1, fl, sum+1);
}
bool check(int s)
{
for(int i = 2; (1<<(i-1)) <= s; ++i)
if(get(s, i-1) && get(s, i)) return false;
return true;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu223.in", "r", stdin);
freopen("sgu223.out", "w", stdout);
#endif
std::ios::sync_with_stdio(0);
std::cin >> n >> k;
for(int i = 0; i < (1<<n); ++i)
if(check(i)) sta[++tot] = i, Map[i] = tot;
f[0][0][1] = 1;
for(int i = 1; i <= n; ++i)
{
memset(f[i&1], 0, sizeof(f[i&1]));
for(int j = 1; j <= tot; ++j)
dfs(sta[j], 0, 1, i&1, 0);
}
for(int i = 1; i <= tot; ++i)
ans += f[n&1][k][i];
std::cout << ans << std::endl;
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}