码迷,mamicode.com
首页 > 系统相关 > 详细

POJ2724:Purifying Machine——题解

时间:2017-12-09 16:49:40      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:mes   das   integer   during   ase   多次   contains   谷歌   清除   

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;
}

 

POJ2724:Purifying Machine——题解

标签:mes   das   integer   during   ase   多次   contains   谷歌   清除   

原文地址:http://www.cnblogs.com/luyouqi233/p/8011654.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!