码迷,mamicode.com
首页 > 编程语言 > 详细

PKU 2531 Network Saboteur(dfs+剪枝||随机化算法)

时间:2017-02-20 12:58:07      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:space   color   随机   ble   under   cstring   algo   结合   ems   

题目大意:原题链接

给定n个节点,任意两个节点之间有权值,把这n个节点分成A,B两个集合,使得A集合中的每一节点与B集合中的每一节点两两结合(即有|A|*|B|种结合方式)权值之和最大。

标记:A集合:true  B集合:false 

解法一:dfs+剪枝

#include<iostream>
#include<cstring>
using namespace std;
int n,ans;
bool in[25];
int graph[25][25];
void dfs(int i,int cursum)
{
    in[i]=true;
    int maxsum=cursum;
    for(int j=1;j<=n;j++){
        if(!in[j]) maxsum+=graph[i][j];
        else maxsum-=graph[i][j];
    }
    if(maxsum>ans) ans=maxsum;
    if(maxsum>cursum){//枚举+递归 
        for(int j=i+1;j<=n;j++)
            dfs(j,maxsum);
    }//如果加进A组没有使得maxsum增大,则不加进去
    in[i]=false; 
}
int main()
{
    cin>>n;
    memset(in,0,sizeof(in));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            cin>>graph[i][j];
    }
    ans=0;
    dfs(1,0);
    cout<<ans<<endl;
}

解法二:随机化算法(好神奇的思路)

#include<iostream>
#include<cstdlib>  
using namespace std;  
const int TLE=2000;//本题时间限制为2000ms   
int main()  
{  
    int n,m[25][25]; 
    cin>>n; 
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            cin>>m[i][j];   
    }
    /*Random Algorithm*/  
    bool in[25]={false};     
    int time=100*TLE;//使随机次数尽可能大,随机结果尽可能接近最优解  
    int maxsum=0,cursum=0;  
    while(time--){  
        int x=rand()%n+1;//范围:1~n    
        in[x]=!in[x];//改变x所在的集合位置        
        for(int i=1;i<=n;i++){
            if(in[i]!=in[x]) cursum+=m[i][x];          
            else  cursum-=m[i][x];
        }
        if(maxsum<cursum) maxsum=cursum;     
    }
    cout<<maxsum<<endl;
}

PKU 2531 Network Saboteur(dfs+剪枝||随机化算法)

标签:space   color   随机   ble   under   cstring   algo   结合   ems   

原文地址:http://www.cnblogs.com/freinds/p/6418599.html

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