题意:给你一个图,图中点之间会有边权,现在问题是把图分成两部分,使得两部分之间边权之和最大。

目前我所知道的有四种做法:

方法一:状态压缩

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
/*
用状态压缩枚举,297ms。 题意:给你一个图,图中点之间会有边权,现在问题是把图分成两部分,使得两部分之间边权之和最大。 情况是对称的,也就是说枚举所有的分类情况中,有一半是冗余的。
举个例子来说,有5个节点,1、2、3分配为A组,4、5分配给B组,
这个分类的策略所计算的结果和1、2、3分配为B组,4、5分配给A组是一样的。
因此对称的就不需要再考虑了,如状态压缩时101和010,只要考虑其中一个就可以了。
至于当枚举到一个状态时,怎么判断它的对称状态已经枚举过了,采用异或就可以了。 */
using namespace std;
const int maxn=;
int n;
int w[maxn][maxn];
//int vis[maxn];
int visit[*];
int ans=;
int set1[maxn];
int set2[maxn];
int idx1,idx2;
int main()
{
int l;
//cout<<(1<<20)<<endl;
cin>>n; memset(w,,sizeof(w));
for(int i=;i<=n;i++){
for(int j=;j<=i;j++)
scanf("%d",&l);
for(int j=i+;j<=n;j++){
scanf("%d",&l);
w[i][j]=w[j][i]=l;
}
}
memset(vis,,sizeof(vis));
memset(visit,,sizeof(visit));
int all=<<n-;
ans=;
//用状态压缩来枚举两组的情况
for(int i=;i<(<<n)-;i++){
//对称的就不需要再考虑了,如101和010,只要考虑其中一个就可以了,用异或即可求出对称的状态。
if(!visit[all^i]){
visit[i]=;
idx1=idx2=;
//将编号存入两个数组中去,而不是用vis标记,从原本的1000+ms减少到297ms
for(int j=;j<n;j++){
if(i&(<<j))
set1[idx1++]=j+;
else
set2[idx2++]=j+;
}
int tot=;
for(int k=;k<idx1;k++){
for(int t=;t<idx2;t++){
tot+=w[set1[k]][set2[t]];
}
}
if(tot>ans)
ans=tot;
}
}
printf("%d\n",ans);
return ;
}

方法二:dfs枚举

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
/*
AC
dfs暴力枚举 547ms
*/
using namespace std;
const int maxn=;
int n;
int w[maxn][maxn];
int vis[maxn];
int set1[maxn];
int set2[maxn];
int idx1,idx2;
int ans=;
void dfs(int u){
if(u==n+){
int tot=;
idx1=idx2=;
for(int i=;i<=n;i++){
if(vis[i])
set1[idx1++]=i;
else
set2[idx2++]=i;
}
for(int k=;k<idx1;k++){
for(int t=;t<idx2;t++){
tot+=w[set1[k]][set2[t]];
}
}
if(tot>ans)
ans=tot;
return ;
}
vis[u]=;
/*
之前还用for循环,额,脑残了。。。
for(int i=u+1;i<=n+1;i++){
dfs(i);
}
*/
dfs(u+);
vis[u]=;
dfs(u+); }
int main()
{
int l;
cin>>n;
//cout<<(1<<19)<<endl;
memset(w,,sizeof(w));
for(int i=;i<=n;i++){
for(int j=;j<=i;j++)
scanf("%d",&l);
for(int j=i+;j<=n;j++){
scanf("%d",&l);
w[i][j]=w[j][i]=l;
}
}
memset(vis,,sizeof(vis));
dfs();
printf("%d\n",ans);
return ;
}

方法三:大牛的解法

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
/*
看了discuss里大牛的做法,然后自己打了一遍,16ms
以下来自discuss里的: 1.等价剪枝:根据对称性剪枝
举个例子来说,有5个节点,1、2、3分配为A组,4、5分配给B组,
这个分类的策略所计算的结果和1、2、3分配为B组,4、5分配给A组是一样的。
那么怎么去除这一半的冗余呢,其实很简单,我们强制第1个节点分配给A组,
那么后面不管怎么分,全体情况都不会有重复的了。 2.换个角度,更高效搜索算法 :如本题逆向思维求最小内部代价
本题要求两个集合之间的边权和最大。反过来,相当于两个集合内部点之间的边权和最小,
令该和为ans。那么我们dfs的目的就是使得ans的值最小。 3.无法达最优:提前剪枝,也就是如果当前的Sum>=ans,就不必继续下去了
*/
using namespace std;
const int maxn=;
int n;
int w[maxn][maxn];
int set1[maxn];
int set2[maxn];
int idx1,idx2;
int tot1,tot2,tot;
int ans; void dfs(int Sum,int idx1,int idx2,int k){
if(Sum>=ans)
return;
else if(k==n+){
ans=Sum;
}
else{
int sum=;
for(int i=;i<idx1;i++){
sum+=w[set1[i]][k];
}
set1[idx1]=k; //若k属于第一个集合
dfs(Sum+sum,idx1+,idx2,k+); sum=;
for(int i=;i<idx2;i++){
sum+=w[set2[i]][k];
}
set2[idx2]=k; //若k属于第二个集合
dfs(Sum+sum,idx1,idx2+,k+);
}
}
int main()
{
int l;
cin>>n;
memset(w,,sizeof(w));
tot=;
for(int i=;i<=n;i++){
for(int j=;j<=i;j++)
scanf("%d",&l);
for(int j=i+;j<=n;j++){
scanf("%d",&l);
w[i][j]=w[j][i]=l;
tot+=l;
}
}
tot1=;
for(int i=;i<n/;i++){
for(int j=i+;j<n/;j++)
tot1+=w[i][j];
}
tot2=;
for(int i=n/;i<=n;i++){
for(int j=i+;j<=n;j++)
tot2+=w[i][j];
}
ans=tot1+tot2;
idx1=idx2=;
set1[]=; //先把1固定为第一个集合
dfs(,,,);
printf("%d\n",tot-ans);
return ;
}

方法四:随机算法

http://www.cnblogs.com/chujian123/p/3533156.html

POJ 2531 Network Saboteur (枚举+剪枝)的更多相关文章

  1. POJ 2531 Network Saboteur 位运算子集枚举

    题目: http://poj.org/problem?id=2531 这个题虽然是个最大割问题,但是分到dfs里了,因为节点数较少.. 我试着位运算枚举了一下,开始超时了,剪了下枝,1079MS过了. ...

  2. POJ 2531 Network Saboteur

    http://poj.org/problem?id=2531 题意 :有N台电脑,每两台电脑之间都有个通信量C[i][j]; 问如何将其分成两个子网,能使得子网之间的通信量最大. 也就是说将所有节点分 ...

  3. poj 2531 Network Saboteur 解题报告

    题目链接:http://poj.org/problem?id=2531 题目意思:将 n 个点分成两个部分A和B(也就是两个子集啦), 使得子集和最大(一定很难理解吧,呵呵).举个例子吧,对于样例,最 ...

  4. poj 2531 Network Saboteur( dfs )

    题目:http://poj.org/problem?id=2531 题意:一个矩阵,分成两个集合,求最大的 阻碍量 改的 一位大神的代码,比较简洁 #include<stdio.h> #i ...

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

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

  6. poj 2531 Network Saboteur(经典dfs)

    题目大意:有n个点,把这些点分别放到两个集合里,在两个集合的每个点之间都会有权值,求可能形成的最大权值.   思路:1.把这两个集合标记为0和1,先默认所有点都在集合0里.             2 ...

  7. poj 2531 搜索剪枝

    Network Saboteur Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u ...

  8. Network Saboteur 分类: 搜索 POJ 2015-08-09 19:48 7人阅读 评论(0) 收藏

    Network Saboteur Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10147 Accepted: 4849 Des ...

  9. poj2531 Network Saboteur

    Network Saboteur Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11122   Accepted: 5372 ...

随机推荐

  1. .NET开源工作流RoadFlow-快速入门

    在环境搭建好之后,我们就来学习一下怎样快速创建一个流程,并执行和流转该流程(我们这里讲的只是入门,不涉及到具体流程参数设置). 创建一个流程步骤为:在数据库在创建表-->设计表单-->设置 ...

  2. 公钥私钥 ssl/tsl的概念

    一,公钥私钥1,公钥和私钥成对出现2,公开的密钥叫公钥,只有自己知道的叫私钥3,用公钥加密的数据只有对应的私钥可以解密4,用私钥加密的数据只有对应的公钥可以解密5,如果可以用公钥解密,则必然是对应的私 ...

  3. 深入浅出const

    §通常,如果一个对象通过引用方式传到函数f中,而函数f又不会通过修改对象的数据成员的值改变该对象的状态,那么,我们最好将f的参数标记为const,这样可以预防对参数的误写,同时有些编译器还可对这种情况 ...

  4. JavaScript高级程序设计之Date类型

    ECMAScript 中的 Date 类型是在早期 Java 的 java.util.Date 类基础上构建的. Date 类型使用自 UTC (国际协调时间)1970年1月1日午夜(零时)开始经过的 ...

  5. lucene .NET 搜索图片 功能实现

    关于搜索部分 1想建立索引.构建jpg图片解析器,在索引时将jpg图片的exif信息及其文本信息如名称,存放路径,大小,日期等等加入索引!具体实现代码如下: public void BulidInde ...

  6. [小技巧]让C#的空值处理变得更优雅

    参考 http://www.codeproject.com/Articles/739772/Dynamically-Check-Nested-Values-for-IsNull-Values?msg= ...

  7. 4.FPGA芯片管脚解释

    用户I/O:不用解释了.   配置管脚: MSEL[1:0] 用于选择配置模式,比如AS.PS等. DATA0 FPGA串行数据输入,连接到配置器件的串行数据输出管脚. DCLK FPGA串行时钟输出 ...

  8. “我爱淘”冲刺阶段Scrum站立会议4

    完成任务: 完成了搜索界面的Activity的编写. 计划任务: 实现数据库的链接,用户可以查到自己需要的书籍的信息. 遇到问题: 数据库的操作,实现查询功能:

  9. AlarmManager使用注意事项

    在使用AlarmManager实现闹钟需要注意的是,intent和pendingintend的context如果是activity,那么当activity回收之后,context对象则不能被Alarm ...

  10. 【Largest Rectangle in Histogram】cpp

    题目: Given n non-negative integers representing the histogram's bar height where the width of each ba ...