• C——Network Saboteur (POJ2531)


    题目:
    A university network is composed of N computers. System administrators gathered information on the traffic between nodes, and carefully divided the network into two subnetworks in order to minimize traffic between parts. 
    A disgruntled computer science student Vasya, after being expelled from the university, decided to have his revenge. He hacked into the university network and decided to reassign computers to maximize the traffic between two subnetworks. 
    Unfortunately, he found that calculating such worst subdivision is one of those problems he, being a student, failed to solve. So he asks you, a more successful CS student, to help him. 
    The traffic data are given in the form of matrix C, where Cij is the amount of data sent between ith and jth nodes (Cij = Cji, Cii = 0). The goal is to divide the network nodes into the two disjointed subsets A and B so as to maximize the sum ∑Cij (i∈A,j∈B).

    Input

    The first line of input contains a number of nodes N (2 <= N <= 20). The following N lines, containing N space-separated integers each, represent the traffic matrix C (0 <= Cij <= 10000). 
    Output file must contain a single integer -- the maximum traffic between the subnetworks. 

    Output

    Output must contain a single integer -- the maximum traffic between the subnetworks.

    Sample Input

    3
    0 50 30
    50 0 40
    30 40 0
    

    Sample Output

    90

    解题思路:
    首先这个题目的题意就比较难理解。题目大意:有n个点,每两个点之间都有一段距离,现在要把这些点分为两部分,使得一个部分的点到另一个部分所有的点的距离和最大。(学过离散的就知道这是一个完全图)比如题中的例子:就是一个K3图(3个顶点的完全图,一个三角形),设顶点为A,B,C.由题意可知:A到B的距离为30,B到C为40,C到A为50.当把A放一边,B,C放一边时,总距离为:A到B的距离(30)+A到C的距离(50)=80.当把C放一边,A,B一边时,总距离为AC+BC=90,另一种为30+40=70.所以最大的距离和为90.
    看懂题目的可能都知道要用枚举来找最大距离和,但是怎么枚举呢?用for循环?肯定行不通的。这里就用”二进制枚举“来枚举所有情况并找到最大值。

    二进制枚举(非递归):
    用数组的值为0或1来把所有的点来分为两部分。
     1 int a[10002];
     2 memset(a,0,sizeof(a)); //清零。
     3 for (int i=0;i<n;i++) //n:枚举的次数。
     4 {
     5   a[0]++;     //第一位加一。
     6  for (int j=0;j<n;j++)
     7    if (a[j]==2)  
     8      {
     9        a[j]=0;   //当这一位等于2时,又清零
    10        a[j+1]++;  //并使下一位加一。
    11      }
    12 }
    
    
    代码可能不好理解。下面模拟过程。
    开始时的数组: 00000
    a[0]++;后 10000
    a[0]++等于2后,a[0]=0;a[0+1]++;01000
    接下来是:
    11000
    00100
    10100
    01100
    ......
    11111
    这样就把所有的情况都枚举出来了。
    下一步就只要把所有枚举中0或1的所有对应值求和,并找到最大值就可以了。
    全部代码如下:
    #include <iostream>
    #include <cstring>
    #include <cmath>
    using namespace std;
    int a[22][22],tab[22];
    
    int main()
    {
        int n,i,j,k,ans=0,sum=0,z;
        cin >>n;
        for (i=1;i<=n;i++)
            for (j=1;j<=n;j++)
            cin >>a[i][j];
            k=pow(2,n-1);   //枚举的情况总数。
    
        for (i=1;i<=k;i++)
        {
            tab[1]++;
            sum=0;
            for (j=1;j<=n;j++)
                if (tab[j]==2)
            {
               tab[j]=0;
               tab[j+1]++;
            }
            else break;
            for (j=1;j<=n;j++)
            {
                if (tab[j]==0)continue;  //找到每一个为1的点。
                for (z=1;z<=n;z++)    
                    if (tab[z]==0)           //并把这个1到所有0的距离求和。
                    sum+=a[j][z];
            }
            ans=max(ans,sum);    //找到最大的的和。
        }
        cout <<ans<<endl;
        return 0;
    }
    
    
    




  • 相关阅读:
    Get-CrmSetting返回Unable to connect to the remote server的解决办法
    Dynamics 365中的常用Associate和Disassociate消息汇总
    Dynamics 365 Customer Engagement V9 活动源功能报错的解决方法
    Dynamics Customer Engagement V9版本配置面向Internet的部署时候下一步按钮不可点击的解决办法
    Dynamics 365检查工作流、SDK插件步骤是否选中运行成功后自动删除系统作业记录
    注意,更改团队所属业务部门用Update消息无效!
    Dynamics 365的审核日志分区删除超时报错怎么办?
    Dynamics 365使用Execute Multiple Request删除系统作业实体记录
    Dynamics 365的系统作业实体记录增长太快怎么回事?
    Dynamics CRM日期字段查询使用时分秒的方法
  • 原文地址:https://www.cnblogs.com/shendeng23/p/7287186.html
Copyright © 2020-2023  润新知