問題:n*n的棋盤放置n個點辑奈,保證每一行,每一列都有且只有一個點已烤,有幾種放置方式鸠窗?
一、組合數(shù)解法:
ans=n!
二胯究、狀態(tài)壓縮DP:
方案數(shù)目:f[0]=1,其他初始化為0
狀態(tài):10010=>21+24=2+16=18->一個整數(shù)表示一種狀態(tài)->
拆解整數(shù)->表示了所有的部件的當(dāng)前狀態(tài)
遍歷順序(第一層):s:1 -> (1<<n-1)=>(111..11(n個位))
(第二層):i:1->n(枚舉所有的部件)
已知當(dāng)前的狀態(tài)是s:
操作一:s&(1<<(n-1))
if(s&(1<<(n-1)))
{
操作二:s^(1<<(n-1))稍计,這是根據(jù)s,找到的上一個的所有的狀態(tài)
令tmp=s^(1<<(n-1))
f[s]+=f[tmp]//累加得出答案
}
神犇博客:
https://blog.csdn.net/soundwave_/article/details/52100038
(這里只講我的具體理解)
具體代碼:
#include <iostream>
#include <stdio.h>
using namespace std;
int f[1<<21];
int main()
{
int n, temp;
int s, i;
scanf("%d", &n);
memset(f,0,sizeof(f));
f[0] = 1;//邊界條件
for(s = 1; s <= (1<<n)-1; s++)
{
for(i = 1; i <= n; i++)
if(s & (1<<(i-1)))//排除掉第i行所有不能放置的位置之后的可放位置
{
temp = s ^ (1<<(i-1));//可以得到s狀態(tài)的狀態(tài)
f[s] += f[temp];//s狀態(tài)下的方案數(shù)
}
}
printf("%d", f[(1<<n)-1]);
return 0;
}