zoukankan      html  css  js  c++  java
  • 【9505】部落卫队

    Time Limit: 1000ms second
    Memory Limit: 32m 问题描述:
    原始部落byteland中的居民们为了争夺有限的资源,经常发生冲突。几乎每个居民都有他的仇敌。部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入 伍,并保证队伍中任何2个人都不是仇敌。
    编程任务:
    给定byteland 部落中居民间的仇敌关系,编程计算组成部落卫队的最佳方案。

    Input

    第1行有2个正整数n和m,表示byteland部落中有n个居民,居民间有m个仇敌关系。居民编号为1,2,…,n。接下来的m行中,每行有2个正整数u和v,表示居民u与居民v是仇敌。 (居民编号为1,2,...,n)

    Output

    程序运行结束时,将计算出的部落卫队的最佳组建方案输出到文件output.txt 中。文件 的第1行是部落卫队的顶人数;文件的第2行是卫队组成xi,1≤i≤n,xi=0表示居民i不在卫队中,xi=1表示居民在卫队中。(第二行数据后都加一空格,最后以回车结束)

    Sample Input

    7 10
    1 2
    1 4
    2 4
    2 3
    2 5
    2 6
    3 5
    3 6
    4 5
    5 6
    
    
    

    Sample Output

    3
    1 0 1 0 0 0 1 
    

    【题解】

    用一个二维数组来表示某个人的所有仇敌关系,a[i][0]表示i号人他的仇敌数量,a[i][1..a[i][0]]则表示这a[i][0]个人具体是谁。

    当我们想要把第i个人放入这个卫队中时,我们先看下现在的卫队中是否有人以他为仇敌。如果没有就放进去。然后我们需要更新这支队伍的仇敌列表,即不能进入这支新队伍的人。在找的时候一边更新最优解就好。

    这题仍然是组合问题,因为1 3 7 和 3 1 7是一样的。所以扫描到x的时候从x+1开始扫描就好。

    【代码】

    在vijos上也有这题P1593,那里有10个数据,平台上只剩2个数据了。

    #include <cstdio>
    
    int n,m,num = 0,max_n = 0;
    int a[1001][1001]; //3MB
    int bo[1001],ans[1001],tt[1001];
    
    void input_data()
    {
        scanf("%d %d",&n,&m);
        for (int i = 1; i <= n;i++)
            for (int j = 1; j<= m;j++) //一开始的初始化 所有人都没有仇敌
                a[i][j] = 0;
        for (int i = 1;i <= m;i++) //增加m个仇敌关系
            {
                int x,y;
                scanf("%d %d",&x,&y);
                a[x][0]++;a[x][a[x][0]] = y; //两个人都各增加一个仇敌 并记录下来
                a[y][0]++;a[y][a[y][0]] = x;
            }
        for (int i = 1;i <= n;i++) //一开始所有人都可以进入这个队伍
            bo[i] = 0;
    }
    
    void sear_ch(int x)
    {
        bo[x] = 1; //这个人入队后直接变成1 之前肯定是0的
        for (int i = 1;i <= a[x][0];i++) //这个人地仇敌,每个仇敌的bo都递增,注意不要直接变成0.比如里面有两个人
            //仇敌都有3。我们这层搜索完后,应该递减,而不是直接变成false,这样bo[3]==1,我们下次就不会把3给加进去了。
            bo[a[x][i]]++;
        ans[++num] = x; //记录答案
        if (num >max_n) //如果大于最大值 就更新解
            {
                max_n = num;
                for (int i = 1;i <= max_n;i++)
                    tt[i] = ans[i];
            }
        for (int i = x+1;i <= n;i++) //从x+1开始 如果可以加入就加入
            if (bo[i] == 0)
                sear_ch(i);
        for (int i = 1;i <=a[x][0];i++)//注意是递减不是直接变成0
            bo[a[x][i]]--;
        bo[x] = 0; //本身是可以直接变成0的,因为bo[x]一开始直接变成1,后来仇敌增加,此外没有涉及到,有也已经递减了。
        num--;
    }
    
    void get_ans()
    {
        for (int i = 1;i <= n;i++)
            sear_ch(i);
        for (int i = 1;i <= n;i++) //根据记录的答案改变各个编号的人的值。最后输出就好
            bo[i] = 0;
        for (int i = 1;i <= max_n;i++)
            bo[tt[i]] = 1;
    }
    
    void output_ans()
    {
        printf("%d
    ",max_n);
        for (int i = 1;i <= n;i++)
            printf("%d ",bo[i]);
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        input_data();
        get_ans();
        output_ans();
        return 0;
    }
    


     

     

  • 相关阅读:
    方法名的string类型应用(补)
    unity3D里面的点乘和叉乘
    C# 计算时间日期
    iOS设备屏幕分辨率分布
    免证书发布ipa文件真机测试
    unity3D +php +数据库
    windows下mysql5.1忘记root密码解决方法[win7]
    springboot配置多数据源(JdbcTemplate方式)
    【转】Google Chrome中顺时针/逆时针滚动圆的含义
    Redis内存模型(2):存储细节
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632439.html
Copyright © 2011-2022 走看看