HDU 6321 状态压缩

题目:http://acm.hdu.edu.cn/showproblem.php?pid=6321

题意:t组测试

   每组n个点,m次操作,是一个无向图。  ‘+’ u v 表示增加一条边u,v ;‘-’则相反,保证减边一定存在。

   十个点状态dp,用二进制表示这个点的状态。

   代码有每一步的解释

 

#include <bits/stdc++.h>
#define rep(i,a,n)  for(int i=a;i<n;i++)
typedef long long  ll;
const ll mod=1000000007;

int _,n,q,u,v,t;

int dp[1234][20],f[1234];
char s[20]; 

using namespace std;
int main()
{
	rep(i,1,1024)  f[i]=f[i>>1]+(i&1);//初始化,f[i]存储i的二进制有多少个1 
	
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&n,&q);
		memset(dp,0,sizeof(dp));
		
		rep(i,0,(1<<n))dp[i][0]=1;// 边数为0的状态有1种,初始化为1 
		
		rep(i,0,q)
		{
			scanf("%s %d %d",s,&u,&v);
			u--;  v--;//若输入 1,2 要状态表示
			// 1:第一位二进制为1,   2:第二位二进制为1
			//1=2的0次方     1=2的一次方 所以减减 
			//很神奇对吧,u减减后2的(u-1)的次方二进制下 1所在的位就是第u位 
		int Ss=(1<<u)+(1<<v); //上面减减后状态表示 
		     
		for(int S=0;S<=(1<<n)-1;S++)//枚举各种点集状态 
		{
		    if((S&Ss)==Ss)//若这种状态包含输入的两个点则处理 
			{
			    for(int j=1;j<=f[S];j++)
			       {
			       	    dp[S][j]+=(s[0]=='+'?dp[S^Ss][j-1]:(mod-dp[S^Ss][j-1]));
			       	       // dp[S^Ss][j-1] 是不包含这两个点 且边数减少一 
						   if(dp[S][j]>=mod)
						   dp[S][j]-=mod; 
				   }
			}	
     	}
		for(int j=1;j<=n/2;j++)
		  printf("%d%c",dp[(1<<n)-1][j]," \n"[j==n/2]);
	    
	    }
	}

  return 0;	
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wym_king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值