POJ 2724 Purifying Machine

题目:http://poj.org/problem?id=2724

相差一位的可以同时删除,所以就剩下一次,只要求出相差一位的有多少对,用总数减去就可以了。

同时,两个数中1的个数都是偶数或奇数个的话,那么不可能相差一位,所以根据1的个数可以分成两组。

判断是否相差一位用位运算

代码:

View Code
  1 #include<stdio.h>
2 #include<string.h>
3 #define maxn 1024
4
5 int n,m,l,r;
6 int left[maxn],right[maxn],mark[maxn];
7 bool visit[maxn],map[maxn][maxn];
8 //判断是否相差一位
9 bool judge(int x,int y)
10 {
11 int z=x^y;
12 if(z&&(z&(z-1))==0)
13 return 1;
14 return 0;
15 }
16
17 void get_map()
18 {
19 int i,j,k,num1,num2,f1,f2;
20 char str[101];
21 l=0;r=0;
22 memset(visit,0,sizeof(visit));
23 while(m--)
24 {
25 scanf("%s",str);
26 f1=0;f2=0;num1=0;num2=0;k=1;
27 for(i=n-1;i>=0;i--)
28 {
29 if(str[i]=='*')
30 {
31 num1+=k;
32 f1++;
33 }
34 else if(str[i]=='1')
35 {
36 num1+=k;f1++;
37 num2+=k;f2++;
38 }
39 k*=2;
40 }
41 //根据1是奇数个还是偶数个分成左右两部分
42 if(!visit[num1])
43 {
44 if(f1%2==1)
45 left[l++]=num1;
46 else
47 right[r++]=num1;
48 visit[num1]=1;
49 }
50 if(!visit[num2])
51 {
52 if(f2%2==1)
53 left[l++]=num2;
54 else
55 right[r++]=num2;
56 visit[num2]=1;
57 }
58 }
59 //根据是否相差一位建图
60 for(i=0;i<l;i++)
61 for(j=0;j<r;j++)
62 if(judge(left[i],right[j]))
63 map[left[i]][right[j]]=1;
64 }
65
66 bool dfs(int k)
67 {
68 int j,i;
69 for(j=0;j<r;j++)
70 {
71 i=right[j];
72 if(map[k][i]&&!visit[i])
73 {
74 visit[i]=1;
75 if(mark[i]==-1||dfs(mark[i]))
76 {
77 mark[i]=k;
78 return 1;
79 }
80 }
81 }
82 return 0;
83 }
84
85 void solve()
86 {
87 int i,count=0;
88 memset(mark,-1,sizeof(mark));
89 for(i=0;i<l;i++)
90 {
91 memset(visit,0,sizeof(visit));
92 if(dfs(left[i]))
93 count++;
94 }
95 printf("%d\n",l+r-count);
96 }
97
98 int main()
99 {
100 while(scanf("%d%d",&n,&m)!=EOF)
101 {
102 if(n==0&&m==0)
103 break;
104 get_map();
105 solve();
106 }
107 return 0;
108 }

  

原文地址:https://www.cnblogs.com/lujiacheng/p/2117279.html