zoukankan      html  css  js  c++  java
  • 1156. Two Rounds 夜

    http://acm.timus.ru/problem.aspx?space=1&num=1156

    经典一维背包的原型是二维DP递推 由于其特殊性而被简化成了一维 就变成了背包

    此题的特殊性导致无法简化成一维背包 所以用二维DP递推

    思路:

    先把数据分成m组 每组有两个集合 这两个集合只能任选其一

    根据每个集合的组数和元素个数进行递推

    代码及其注释:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #define LL long long
    
    using namespace std;
    
    const int N=150;
    vector<int>hate[N];//根据不在一组而建立排斥关系
    int f[N];//属于第几组 的 那个集合
    int num1[N],num2[N];//第 i 组的集合 1 中元素个数 集合 2 中元素个数
    int choose[N][N];//更新到第 i 组时 人数为 j 时是 选择了第 i 组的哪个集合
    int sele[N];//第 i 组选择了哪个集合
    bool dfs(int x,int k)
    {
        if(f[x])
        {
            if(f[x]==k)
            return true;
            return false;//如果矛盾 则无解
        }
        f[x]=k;
        if(k>0) ++num1[k];
        else  ++num2[-k];
        for(unsigned int i=0;i<hate[x].size();++i)
        {
            if(!dfs(hate[x][i],-k))
            return false;
        }
        return true;
    }
    int main()
    {
        //freopen("data.txt","r",stdin);
        int n,m;
        while(cin>>n>>m)
        {
            while(m--)
            {
                int i,j;
                cin>>i>>j;
                hate[i].push_back(j);
                hate[j].push_back(i);
            }
            memset(num1,0,sizeof(num1));
            memset(num1,0,sizeof(num2));
            memset(f,0,sizeof(f));
            int I=1;
            int l;
            for(l=1;l<=2*n;++l)
            {
                if(f[l]==0)
                {
                    if(!dfs(l,I))
                    break;
                    ++I;
                }
            }
            if(l<=2*n)
            {printf("IMPOSSIBLE\n");continue;}//有矛盾的情况
            memset(choose,0,sizeof(choose));
            choose[0][0]=1;
            int m=I-1;
            for(int i=0;i<m;++i)
            {
                for(int j=0;j<=n;++j)
                {
                    if(choose[i][j]==0)
                    continue;
                    choose[i+1][j+num1[i+1]]=1;
                    choose[i+1][j+num2[i+1]]=-1;
                }
            }
            if(choose[m][n]==0)//无解
            {printf("IMPOSSIBLE\n");continue;}
             int k=n;
             for(int i=m;i>=1;--i)
             {
                 sele[i]=choose[i][k];
                 if(choose[i][k]>0)
                 k=k-num1[i];
                 else
                 k=k-num2[i];
             }
             for(int i=1;i<=2*n;++i)
             {
                 if((f[i]>0&&sele[f[i]]==1)||(f[i]<0&&sele[-f[i]]==-1))
                 {
                    printf("%d ",i);
                 }
             }
             printf("\n");
             for(int i=1;i<=2*n;++i)
             {
                 if(!(f[i]>0&&sele[f[i]]==1)&&!(f[i]<0&&sele[-f[i]]==-1))
                 {
                    printf("%d ",i);
                 }
             }
             printf("\n");
        }
        return 0;
    }
    
  • 相关阅读:
    My97DatePicker使用说明文档
    内存溢出之Tomcat内存配置
    myeclipse控制台不显示tomcat信息
    修改 MyEclipse 编辑区域背景颜色
    window.open() 弹出窗体居中
    javascript控制页面控件隐藏显示的两种方法
    (转)MyEclipse7.5.0版注册码破解及激活操作
    [置顶] Android代码读取 android 设备的电池信息
    [置顶] Android代码获得我们手机的cpu序列号
    [置顶] Android高手进阶教程Android常用名令集锦(图文并茂)!
  • 原文地址:https://www.cnblogs.com/liulangye/p/2736125.html
Copyright © 2011-2022 走看看