poj2531——dfs递归枚举+小剪枝

POJ 2531  dfs递归枚举

Network Saboteur

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 9580   Accepted: 4560

Description

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

题意:将给定图分成两个子图A,B,使A中结点i到B中结点j的距离和最大,输出最大值初看以为是图论题,原来可以直接dfs过。。直接dfs递归枚举顺便剪枝

//poj2531_dfs递归枚举
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

const int maxn=30;

int N,C[maxn][maxn];
int dist[maxn];
int ans;
bool vis[maxn];//1表示在集合A,0表示还在集合B

void dfs(int cur,int step,int limit,int sum)
{
    if(cur+limit-step>N) return;//这个剪枝貌似有点弱,只是从256ms优化到了188ms
    for(int i=1;i<=N;i++){ //从B添加结点cur掉A中
        if(vis[i]) sum-=C[cur][i];//减少到A的边
        else sum+=C[cur][i];//增加到B的边
    }
    if(step==limit){ //到达限制,比较ans,返回
        if(sum>ans) ans=sum;
        return;
    }
    vis[cur]=1;
    for(int i=cur+1;i<=N;i++){
        dfs(i,step+1,limit,sum); //添加下一个
    }
    for(int i=1;i<=N;i++){ //从A中拿回来
        if(vis[i]) sum+=C[cur][i];
        else sum-=C[cur][i];
    }
    vis[cur]=0;//记得还原vis
}

int main()
{
    while(cin>>N){
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++){
                cin>>C[i][j];
                dist[i]+=C[i][j];
            }
        }
        ans=0;
        for(int i=1;i<=N/2;i++){ //枚举A中的结点个数
            for(int st=1;st<=N;st++){ //递归枚举,st为起点
                memset(vis,0,sizeof(vis));
                dfs(st,1,i,0);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

poj2531_dfs

时间: 2024-10-09 17:26:22

poj2531——dfs递归枚举+小剪枝的相关文章

poj1416——dfs递归枚举+记录路径

POJ 1416  dfs递归枚举+记录路径 Shredding Company Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4456   Accepted: 2555 Description You have just been put in charge of developing a new shredder for the Shredding Company Although a "normal" s

HDU 1010 Tempter of the Bone【DFS经典题+奇偶剪枝详解】

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 125945    Accepted Submission(s): 33969 Problem Description The doggie found a bone in an ancient maze, which fascinated him a

C++ 全排列问题——递归枚举法

全排列问题是一道非常经典的递归题目,而递归枚举法求解也是最暴力的一种方法. 例题 洛谷1706 题目描述 输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字. 输入格式 一个整数n. 输出格式 由1-n组成的所有不重复的数字序列,每行一个序列. 每个数字保留 5个场宽. 输入样例 3 输出样例 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 全排列问题--递归枚举法 这是一道经典的递归的题,每次递归枚举第x个数字是几,就是从1到

[leetcode 40. 组合总和 II] 不排序使用哈希表+dfs递归 vs 排序栈+回溯

题目描述 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使用一次. 说明: 所有数字(包括目标数)都是正整数. 解集不能包含重复的组合. 示例 1: 输入: candidates = [10,1,2,7,6,1,5], target = 8, 所求解集为: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ] 示例 2: 输入

Swift枚举-相关值与递归枚举

代码: enum ArithmeticExpression { // 相关值 case Number(Int) // 递归枚举 indirect case Addition(ArithmeticExpression, ArithmeticExpression) indirect case Multiplication(ArithmeticExpression, ArithmeticExpression) indirect case Division(ArithmeticExpression, A

POJ 1321-棋盘问题(DFS 递归)

POJ 1321-棋盘问题 K - DFS Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. Input 输入含有多组测试数据. 每组数据的第一行是两个正整数,n k,用

递归(以及几个关于递归的小例子)

在说递归之前,我给大家说一个小故事,故事就是在说递归之前,我给大家说一个小故事,故事就是在说递归之前,我给大家说一个小故事,故事就是在说递归之前,我给大家说一个小故事,故事就是在说递归之前我给大家说一个小故事...... 这个故事的名字就叫做递归...哈哈. 故事虽然有点扯淡,但它却很好的解释神马叫做递归. 递归的正式定义: 在数学和计算机科学中,递归指由一种(或多种)简单的基本情况定义的一类对象或方法,并规定其他所有情况都能被还原为其基本情况. 例如,下列为某人祖先的递归定义: 某人的双亲是他

hdu4277USACO ORZ dfs暴力枚举+map

//给N个 问rails用着N个rails能构成几个不同的三角形 //dfs暴力枚举+(map) #include<cstdio> #include<cstring> #include<map> #include<iostream> using namespace std ; int ans ; int a[20] ; int n ; int sum = 0 ; struct node { int a , b , c ; bool operator == (

朴素搜索dfs, 简单的剪枝搜索

为做一个项目选择最合适的语言固然重要,但是,掌握一门自己熟练的兵器,也很重要. ===================================================================================================================== 继续总结搜索类的题目,这一类的题目,目前仅分析简单粗暴的dfs搜索,以及简单的剪枝. 参考的题目: http://acm.hdu.edu.cn/showproblem.php?pid=