集训队训练⑨ - Virtual Judge
1.注意判断非法状态
2.用二进制先把所有状态搞出来
3.后面再判断是否合法,如果说合法,那就存到转移的里面
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#define int long long
using namespace std;
const int N = 12, M = 1 << 10, K = 110;
int n,m;
vector<int> state;
int id[M],cnt[M];
vector<int> head[M];
int f[N][K][M];
//检查是否合法
//如果连着两个状态都是1,那必然不合法
bool check(int state)
{
for (int i=0;i<n;i++)
if((state >> i & 1) && (state >> (i + 1) & 1))
return false;
return true;
}
//统计1的个数
int count(int state)
{
int res = 0;
for(int i=0;i<n;i++) res += state >> i & 1;
return res;
}
signed main() {
cin>>n>>m;
for(int i=0;i < 1 << n;i++)
{
// 如果合法
if(check(i)){
state.push_back(i);
// 记录一下位置
id[i] = state.size() - 1;
// 记录一下用了几个
cnt[i] = count(i);
}
}
// 然后就开始连状态变化了
for(int i=0;i<state.size();i ++)
for(int j=0;j<state.size();j++)
{
int a = state[i];int b = state[j];
if((a & b) == 0 && check(a | b)){
head[i].push_back(j);
}
}
f[0][0][0]=1;
for(int i=1;i<=n+1;i++)
for(int j=0;j<=m;j++)
for(int a = 0;a < state.size();a++)
for(int b : head[a]){
int c = cnt[state[a]];
if(j>=c){
f[i][j][a] += f[i-1][j-c][b];
}
}
cout<<f[n+1][m][0]<<endl;
}