题目
分析
- 这道题真是让我笑死
- n=20,m=10 状压可能过不了哦
- 算了试试吧
- 结果拿了九十
- 然后还错了一个点
- 出题人有想啥,卡状压好吧我服了
- 结果是WA,之前的大佬都是打标过的??
- xswl
- 设f[i][j]为到当前第i行,前i-1行状态为j
- 然后先把初始化1打出来
- 方程为 f[i][j|(1<<k-1)]+=f[i-1][j];
- 因为我们的状态是只有上一行影响所以可以开滚动数组
- x^=1; __builtin_popcount(j)这东西能直接得到j在二进制下1的个数
代码
1 #include<iostream>
2 using namespace std;
3 int n,m;
4 int map[30][30];
5 long long f[2][1<<20+1];
6 int a[21];
7 int main ()
8 {
9 cin>>n>>m;
10 for (int i=1,x,y;i<=m;i++) cin>>x>>y,map[x][y]=1;
11 for (int i=1;i<=n;i++)
12 for (int j=1;j<=n;j++)
13 a[i]=(a[i]<<1)+map[i][j];
14 int maxn=(1<<n)-1;
15 int x=1;
16 for (int i=1;i<=n;i++)
17 if (!(a[1]&(1<<i-1)))
18 f[x][(1<<i-1)]=1;
19 for (int i=2;i<=n;i++)
20 {
21 x^=1;
22 for (int j=1;j<=maxn;j++)
23 {
24 if (__builtin_popcount(j)==i-1)
25 {
26 for (int k=1;k<=n;k++)
27 {
28 if (!(j&(1<<k-1))&&!(a[i]&(1<<k-1)))
29 f[x][j|(1<<k-1)]+=f[x^1][j];
30 }
31 }
32 }
33 }
34 long long ans=0;
35 for (int i=1;i<=maxn;i++)
36 if (__builtin_popcount(i)==n)
37 ans+=f[x][i];
38 cout<<ans;
39 }