您的位置:首页 > 其它

状态压缩DP

2016-08-06 16:44 323 查看
K - Necklace
Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:327680KB 64bit IO Format:%I64d & %I64u

Submit Status

Description

Input

Output

Sample Input

Sample Output

Hint

Description

One day , Partychen gets several beads , he wants to make these beads a necklace . But not every beads can link to each other, every bead should link to some particular bead(s). Now , Partychen wants to know how many kinds of necklace he can make.

Input

It consists of multi-case . Every case start with two integers N,M ( 1<=N<=18,M<=N*N ) The followed M lines contains two integers a,b ( 1<=a,b<=N ) which means the ath bead and the bth bead are able to be linked.

Output

An integer , which means the number of kinds that the necklace could be.

Sample Input

3 3
1 2
1 3
2 3


Sample Output

2


题意:

给出N个珠子,要把他们连成串,每个珠子都要用上,有多少种连法。重点是dp状态转移方程。

代码:

/*
给出的珠子要全部用上,因此只要最后的状态dp[i][j]中的j能够与第一个珠子相连就行,其中i表示取珠子
的状态,每多加一颗珠子他的dp数就是加上没加之前的dp数(重点!).
*/
#include<iostream>
#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<queue>
#include<stack>
using namespace std;
int n,m,a,b;
bool d[19][19];
long long dp[1<<19][19]; //用int过不了
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(dp,0,sizeof(dp));
memset(d,0,sizeof(d));
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
a--;         //这里减一是为了后面写循环简便,也可以不减一
b--;
d[b][a]=1;
d[a][b]=1;
}
dp[1][0]=1;     //初始化第一个当放一个钥匙时总数为1
for(int i=0;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
if(dp[i][j]==0) continue; //也可以用!(i&(1<<j))来判断,但后者会更费时
for(int k=1;k<n;k++)      //k也可以从0开始
{
if(!d[k][j]) continue;  //判断k与j是否能连接
if(i&(1<<k)) continue;  //判断第K个钥匙是否已算过
dp[i|(1<<k)][k]+=dp[i][j];
}
}
}
long long ans=0;
for(int i=0;i<n;i++)
{
if(d[0][i]) ans+=dp[(1<<n)-1][i];
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: