前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HDU 6321 状态压缩

HDU 6321 状态压缩

作者头像
用户2965768
发布2018-08-30 16:06:56
3420
发布2018-08-30 16:06:56
举报
文章被收录于专栏:wymwymwym

题目: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;	
} 
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年07月31日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档