POJ2724:Purifying Machine——题解

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

描述
迈克是奶酪工厂的老板。他有2^N个奶酪,每个奶酪都有一个00 ... 0到11 ... 1的二进制数。为了防止他的奶酪免受病毒侵袭,他用一台净化机器来清理感染病毒的奶酪。净化机有N个开关,每个开关有三个状态,1,0和*。一次操作中,最多可用*一次,它可以代替1或0.当机器转到一个特定的状态时,操作将清除所有相应的二进制数字的奶酪。

有一天,迈克的机器被感染了。当麦克发现时,他已经做了一些操作,这台受感染机器操作的奶酪也被感染了。他尽可能快地清洗机器,现在他需要用最少的操作次数来清理被感染的奶酪。如果奶酪被感染,用机器清洗这个奶酪一次或多次将使这种奶酪再次免于病毒;但是如果一个奶酪没有被感染,这个奶酪的操作会使它变坏。

现在已知Mike已经完成的感染操作,你需要找出清理所有受感染的奶酪所需执行的最少操作次数。

输入
有几个测试用例。每个测试用例都包含两个数字N和M(1 <= N <= 10,1 <= M <= 1000)的行开始。以下M行中的每一行都包含机器的开关状态。 N = M = 0的测试用例结束输入,不应该被处理。

输出
对于每个测试用例,输出一行包含一个整数,这是Mike需要做的最小操作数。

示例输入

3 3
* 01
100
011
0 0

示例输出

2

————————————————————

因为题面很麻烦所以谷歌+手动翻译了一下。

首先将原串展开判重离散化,然后二分图最小边覆盖即可。

注意边是双向边所以用一种简单的方法解决最小边覆盖。

我们不拆点,而是连两条边(例如i到j有一条边,则A集合i连B集合j且B集合i连A集合j)

最后匹配数/2即可。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<map>
using namespace std;
const int maxn=2001;
map<int,bool>mp;
int t[maxn],cnt=0,m,n;
bool vis[maxn],a[maxn][maxn]={0};
int shu[maxn]={0};
char s[50];
bool dfs(int i){
    for(int j=1;j<=cnt;j++){
        if(a[i][j]&&!vis[j]){
            vis[j]=1;
            if(!shu[j]||dfs(shu[j])){
                shu[j]=i;
                return 1;
            }
        }
    }
    return 0;
}
void read(){
    cin>>s;
    int sum=0;
    for(int i=0;i<n;i++){
    if(s[i]==‘*‘)sum=sum*2+0;
    else sum=sum*2+s[i]-‘0‘;
    }
    if(!mp[sum]){
    cnt++;mp[sum]=1;t[cnt]=sum;
    }
    sum=0;
    for(int i=0;i<n;i++){
    if(s[i]==‘*‘)sum=sum*2+1;
    else sum=sum*2+s[i]-‘0‘;
    }
    if(!mp[sum]){
    cnt++;mp[sum]=1;t[cnt]=sum;
    }
    return;
}
int main(){
    while(cin>>n>>m){
    if(n==0&&m==0)break;
    memset(a,0,sizeof(a));
    mp.clear();cnt=0;
    for(int i=1;i<=m;i++)read();
    for(int i=1;i<=cnt;i++){
        for(int j=i+1;j<=cnt;j++){
        int k=t[i]^t[j];
        if(k&&(k&(k-1))==0)a[i][j]=a[j][i]=1;
        }
    }
    int ans=0;
    memset(shu,0,sizeof(shu));
    for(int i=1;i<=cnt;i++){
        memset(vis,0,sizeof(vis));
        if(dfs(i))ans++;
    }
    printf("%d\n",cnt-ans/2);
    }
    return 0;
}
时间: 2024-08-29 20:05:04

POJ2724:Purifying Machine——题解的相关文章

POJ2724 Purifying Machine【二分图最小边覆盖】

题目链接: http://poj.org/problem?id=2724 题目大意: 有2^N个奶酪,编号从000-00到111-11,现在有台机器有N个开关,每个开关的状态有3个, 分别是'0'.'1'.'*',每个开关只能有一个状态存在.'*'状态可以替代'0'或'1'状态.比如11*1, 对应为1111或1101.现在有M个奶酪被感染了,每个奶酪的编号为长度为N的二进制字符串. 和开关一样,每一位上除了能为'1'.'0'之外,还可以是'*',表示既能是'0',也能是'1'.比如说 1*1,

POJ2724 Purifying Machine(二分图)

题意: 有2^n个奶酪,对应二进制的数,用清理机输入一个二进制数可以清理对应的奶酪,含有*的算成0和1两个,每次只能出现一个*,现在清理机自身感染细菌,它清理的奶酪都被感染,将清理机消毒后,问最少清理几次能把所有感染的奶酪清理干净. 要点: 这题比较复杂,题意就比较难看懂,算是一个有向图的最大匹配问题,因为带*的同时可以清理两个,所以就是求最多能有几个*,最后结果:总数-最大匹配数,将所有只差一位的二进制数建图,注意这个图是有向图,因为两个只差一位的数合并成一个,建图时是遍历所有的点,一个点用完

POJ 2724 Purifying Machine(最大独立集)

POJ 2724 Purifying Machine 题目链接 题意:这题题意有点没看懂.看了别人的题解, 给出m串长度为n的01串. 有些串中可能包括,这种串能够表示两个串,为1 和为0. 反复的算一种.比方题目中01 100 011 就代表了四个01串 001 101 100 011 如今我们须要消灭掉全部的01串,消灭方式有两种: 1一次消灭一个串. 2假设两个串的区别仅仅有一位的话能够同一时候消灭这两个串. 问最少多少次操作能够消灭全部的01串 思路:把存在的二进制数保存下来,然后去重.

poj 2724 Purifying Machine

Purifying Machine Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5408   Accepted: 1575 Description Mike is the owner of a cheese factory. He has 2N cheeses and each cheese is given a binary number from 00...0 to 11...1. To keep his chee

UVA1663 Purifying Machine

模版集合个数减少是因为匹配串集合中没被匹配过的一对串匹配了.所以就是找一个二分图最大匹配. 代码里没有显式地建立二分图,可以假想两个集合X和Y,由于两个集合都会跑一遍,所以一个匹配会被算两次,返回的时候除以2就行了. 拾起几乎快忘了的匈牙利算法... #include<bits/stdc++.h> using namespace std; const int maxn = 10; const int N = 1<<maxn; #define debug(x)\ bitset<

UVa1663 Purifying Machine (二分图最大匹配,最大流)

链接:http://vjudge.net/problem/UVA-1663 分析:先把原来m个模板串取出来扔进set里去重,然后将去重后的匹配串从1~cnt编号.题目说每个模板串最多一个星号“*”,所以说一个匹配串只有唯一的一个跟它只有一个位上的数字不同的另一个匹配串组合成一个模板串,这就成了二分图最大匹配问题了.然后针对每个匹配串找出和它只有一位数字不同的其它匹配串,把其编号存进数组vector<int> e[i]里.然后对cnt个匹配串以e[i][j]为状态转移进行dfs黑白染色,这样就把

poj 2724 Purifying Machine(二分图最大匹配)

题意: 有2^N块奶酪,编号为00...0到11..1. 有一台机器,有N个开关.每个开关可以置0或置1,或者置*.但是规定N个开关中最多只能有一个开关置*. 一旦打开机器的开关,机器将根据N个开关的状态对状态对应的编号的奶酪进行消毒. 例如:111 -->  对编号111的奶酪进行消毒.    说明:*代表0或1. 例如:1*1  -->  对编号为101和111的奶酪进行消毒. 现在有一些奶酪被污染了.给出这些奶酷的编号. 问最少需要几次对机器进行设定,使得所有的奶酪都被消毒. 思路: 一

POJ - 2724 Purifying Machine 二分图 最大匹配

题目大意:看了别人的题意: 给出m串长度为n的01串,如果某个串中包含'*'号的,那么这个串就可以变成两个串(因为'*'既可以表示0或者1) 比如字符串*01就可以表示成001,或者101 现在的任务是消除所有的串,给出消除串的规则如下: 1一次消灭一个串. 2如果两个串的差别只有一位的话可以同时消灭这两个串. 问至少需要多少次才能消灭这些串 解题思路:先将这些串去重,化成整数,这样就可以得到两个点集了,点集之间的关系就是一个操作能否消除掉两个串,如果可以的话,则这两个串就存在关系了 #incl

[精]poj2724

Purifying Machine Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5027   Accepted: 1455 Description Mike is the owner of a cheese factory. He has 2N cheeses and each cheese is given a binary number from 00...0 to 11...1. To keep his chee