zoukankan      html  css  js  c++  java
  • 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
    ",cnt-ans/2);
        }
        return 0;
    }
  • 相关阅读:
    JS算法练习一
    jquery抖动的按钮
    CSS3教程:box-sizing属性的理解border、padding与容器宽度的关系
    鼠标hover事件
    object 插入元素,插入HTML页面
    点击展开点击收起
    IE支持CSS3圆角
    登录事件,鼠标点击输入框隐藏默认值事件
    复制 动态文本按钮
    凯撒密码、GDP格式化输出、99乘法表
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8011654.html
Copyright © 2011-2022 走看看