FZU 2093 寻找兔子 (状态压缩dp)

来源:互联网 发布:sql语句优化方法 编辑:程序博客网 时间:2024/05/26 05:52

题目链接
对于每一个点,至多有一个没有确定的点,可以确定兔子的位置。

#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include<queue>#include<iostream>using namespace std;#define LL __int64#define cl(a,b) memset(a,b,sizeof(a))#define pb push_backconst int maxn = 16;const int inf  = 1<<25;const __int64 mod = 1000000007;int edge[maxn*10];//使用二进制存边f[x]|=1<<y;多条边的信息int dp[1<<maxn];//表示到达状态i的最小步数,i状态的1表示这个点已经确定/**解法的可能,对于某一点,要么相邻的点全部是确定的,要么只有一个没有确定*/queue<int>q;int main(){    int T;scanf("%d",&T);    while(T--){        int n,m;scanf("%d%d",&n,&m);        cl(edge,0);        for(int i=0;i<=(1<<n);i++)dp[i]=inf;        for(int i=0;i<m;i++){            int x,y;scanf("%d%d",&x,&y);x--;y--;//编号从0开始            edge[x]|=1<<y;            edge[y]|=1<<x;        }        //找到孤立点,自身连边        for(int i=0;i<n;i++)if(!edge[i])edge[i]=1<<i;        q.push(0);dp[0]=0;        while(!q.empty()){            int x=q.front();q.pop();            //找出当前集合x可以到达的所有点的集合cur            int cur=0;            for(int i=0;i<n;i++)if((x&edge[i])==edge[i])cur|=1<<i;            for(int i=0;i<n;i++)for(int j=i+1;j<n;j++)if(dp[cur|(1<<i)|(1<<j)]>dp[x]+1){                dp[cur|(1<<i)|(1<<j)]=dp[x]+1;                q.push(cur|(1<<i)|(1<<j));            }        }        int all = (1<<n)-1;        int ans = dp[all];//第一种情况,这个点相邻的点全部确定了        for(int i=0;i<n;i++)ans=min(ans,dp[all^(1<<i)]);//第二种可能,这个点,相邻的点只有一个没有确定        printf("%d\n",ans==inf?-1:ans);        while(!q.empty())q.pop();    }    return 0;}
0 0
原创粉丝点击