HDU 3657 Game(取数 最小割)经典
Game
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1065 Accepted Submission(s): 449
the following:
● At the beginning, the score is 0;
● If you take a number which equals to x, the score increase x;
● If there appears two neighboring empty grids after you taken the number, then the score should be decreased by 2(x&y). Here x and y are the values used to existed on these two grids. Please pay attention that "neighboring grids" means there exits and only
exits one common border between these two grids.
Since onmylove thinks this problem is too easy, he adds one more rule:
● Before you start the game, you are given some positions and the numbers on these positions must be taken away.
Can you help onmylove to calculate: what's the highest score onmylove can get in the game?
n and m describing the size of the grids is n ×m. k means there are k positions of which you must take their numbers. Then following n lines, each contains m numbers, representing the numbers on the n×m grids.Then k lines follow. Each line contains two integers,
representing the row and column of one position
and you must take the number on this position. Also, the rows and columns are counted start from 1.
Limits: 1 ≤ n, m ≤ 50, 0 ≤ k ≤ n × m, the integer in every gird is not more than 1000.
2 2 1
2 2
2 2
1 1
2 2 1
2 7
4 1
1 1
4
9HintAs to the second case in Sample Input, onmylove gan get the highest score when calulating like this:
2 + 7 + 4 - 2 × (2&4) - 2 × (2&7) = 13 - 2 × 0 - 2 × 2 = 9.
题目描写叙述:n*m的矩阵,每一个位置都有一个正数,一開始你的分数是0。当你取走一个数字时,你的分数添加那个分数。假设你取完数字后。新出现了2个相邻的都是空的格子,那么你的分数降低2 * ( x & y),x,y是那两个格子的原始数值。
同一时候有一些附加条件,有一些格子的数字是必须拿走的。
解题:与方格取数几乎相同。注要多了两个不同的条件。
1.取相邻的格子则要降低2*(x&y) 建图时。相邻两个格子之间建边容量为2*(x&y) 2.有K个格子是必须取的,则与必须取的点相连的点S或T的边的容量为INF。这样在求最小割时就不会被割了。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define captype int const int MAXN = 100010; //点的总数
const int MAXM = 400010; //边的总数
const int INF = 1<<30;
struct EDG{
int to,next;
captype cap,flow;
} edg[MAXM];
int eid,head[MAXN];
int gap[MAXN]; //每种距离(或可觉得是高度)点的个数
int dis[MAXN]; //每一个点到终点eNode 的最短距离
int cur[MAXN]; //cur[u] 表示从u点出发可流经 cur[u] 号边
int pre[MAXN]; void init(){
eid=0;
memset(head,-1,sizeof(head));
}
//有向边 三个參数。无向边4个參数
void addEdg(int u,int v,captype c,captype rc=0){
edg[eid].to=v; edg[eid].next=head[u];
edg[eid].cap=c; edg[eid].flow=0; head[u]=eid++; edg[eid].to=u; edg[eid].next=head[v];
edg[eid].cap=rc; edg[eid].flow=0; head[v]=eid++;
}
captype maxFlow_sap(int sNode,int eNode, int n){//n是包含源点和汇点的总点个数。这个一定要注意
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
pre[sNode] = -1;
gap[0]=n;
captype ans=0; //最大流
int u=sNode;
while(dis[sNode]<n){ //推断从sNode点有没有流向下一个相邻的点
if(u==eNode){ //找到一条可增流的路
captype Min=INF ;
int inser;
for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to]) //从这条可增流的路找到最多可增的流量Min
if(Min>edg[i].cap-edg[i].flow){
Min=edg[i].cap-edg[i].flow;
inser=i;
}
for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to]){
edg[i].flow+=Min;
edg[i^1].flow-=Min; //可回流的边的流量
}
ans+=Min;
u=edg[inser^1].to;
continue;
}
bool flag = false; //推断是否能从u点出发可往相邻点流
int v;
for(int i=cur[u]; i!=-1; i=edg[i].next){
v=edg[i].to;
if(edg[i].cap-edg[i].flow>0 && dis[u]==dis[v]+1){
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag){
u=v;
continue;
}
//假设上面没有找到一个可流的相邻点。则改变出发点u的距离(也可觉得是高度)为相邻可流点的最小距离+1
int Mind= n;
for(int i=head[u]; i!=-1; i=edg[i].next)
if(edg[i].cap-edg[i].flow>0 && Mind>dis[edg[i].to]){
Mind=dis[edg[i].to];
cur[u]=i;
}
gap[dis[u]]--;
if(gap[dis[u]]==0) return ans; //当dis[u]这样的距离的点没有了,也就不可能从源点出发找到一条增广流路径
//由于汇点到当前点的距离仅仅有一种。那么从源点到汇点必定经过当前点。然而当前点又没能找到可流向的点,那么必定断流
dis[u]=Mind+1;//假设找到一个可流的相邻点。则距离为相邻点距离+1,假设找不到,则为n+1
gap[dis[u]]++;
if(u!=sNode) u=edg[pre[u]^1].to; //退一条边
}
return ans;
}
int main()
{
int n,m,k,cost[55][55],flag[55][55];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
while(scanf("%d%d%d",&n,&m,&k)>0)
{
init();
int s=n*m,t=n*m+1 , ans=0;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
scanf("%d",&cost[i][j]);
ans+=cost[i][j];
}
int x,y;
memset(flag,0,sizeof(flag));
while(k--)
{
scanf("%d%d",&x,&y); x--; y--;
flag[x][y]=1;
}
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if((i+j)&1)
{
addEdg(s , i*m+j , flag[i][j]==0?cost[i][j]:INF);
for(int e=0; e<4; e++)
{
x=i+dir[e][0];
y=j+dir[e][1];
if(x>=0&&x<n&&y>=0&&y<m)
addEdg(i*m+j, x*m+y,2*(cost[i][j]&cost[x][y]));
}
}
else
addEdg(i*m+j,t,flag[i][j]==0?cost[i][j]:INF); ans-=maxFlow_sap(s , t, t+1);
printf("%d\n",ans);
}
}
HDU 3657 Game(取数 最小割)经典的更多相关文章
- LibreOJ #6007. 「网络流 24 题」方格取数 最小割 最大点权独立集 最大流
#6007. 「网络流 24 题」方格取数 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- 【BZOJ1475】方格取数 [最小割]
方格取数 Time Limit: 5 Sec Memory Limit: 64 MB[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一 ...
- HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]
题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...
- 【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型
最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那 ...
- 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)
HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...
- HDU 1569 方格取数(2) (最小割)
方格取数(2) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]
嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...
- HDU 6214.Smallest Minimum Cut 最少边数最小割
Smallest Minimum Cut Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Oth ...
- HDU 1569 方格取数(2)(最大流最小割の最大权独立集)
Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大. ...
随机推荐
- C#,一种简单的方式实现滚动鼠标缩放图片,平移
1.缩放 private void ImageShow_Load(object sender, EventArgs e) { pictureBox1.Load(@"E:\SQ1.jpg&qu ...
- css对html中表格单元格td文本过长的处理
参考 http://www.cnblogs.com/lekko/archive/2013/04/30/3051638.html http://www.zhangxinxu.com/wordpress/ ...
- Rust学习资源和路线
Rust学习资源和路线 来源 https://rust-lang-cn.org/article/23 学习资源 The Rust Programming Language 堪称Rust的"T ...
- 剑指offer42:翻转单词顺序 VS 左旋转字符串(更高效、简便的解法)
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母一样处理.例如输入字符串"I am a student." ,则输出" ...
- xml读取 避开并发(xml的一些操作)
很多地方读取文件可能会出现并发现象 处理: 使用FileMode.Open, FileAccess.Read, FileShare.ReadWrite 避开并发 public static List& ...
- vue-cli打包之后页面为空的问题。
做了一个demo,想看一下打包之后的样子,发现页面是空的. 发现问题就要解决: 1.首先看控制台没有报任何错误,那就证明我们的代码是没有任何问题的. 只能是路径问题造成的. 2.在路由router/i ...
- 【POJ3667】Hotel(线段树)
题意:有n个依次编号的元素,要求维护以下两个操作: 1.询问整个数列中是否有长度>=x的连续的一段未被标记的元素,若无输出0,若有输出最小的开始编号ans并将[ans,ans+x-1]标记 2. ...
- BZOJ【1606】购买干草
1606: [Usaco2008 Dec]Hay For Sale 购买干草 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 859 Solved: 63 ...
- 自定义JS类,并扩展其方法和属性
function CT() { } CT.prototype.P = "TTT"; CT.Test = function () { alert(arguments[0]); }; ...
- XmlRootElement
作用是 java对象 <---> xml文件 之间的转换 JAXB Annotation @XmlRootElement // xml 文件的根元素 @XmlElement @Xm ...