题意:给一个地图,地图上的每个位置是空地或一个炮或一些敌人,给定每个炮的方向(上/下/左/右),每个炮只能打一个位置且炮弹轨迹不能相交,问最多打到多少敌人

原题貌似是TC SRM 627的题,题解在这里

考虑一开始让每个炮都打敌人最多的位置,这样轨迹有可能相交,我们要做的就是合理规划,缩短某些炮击的距离使轨迹不相交的同时能打到的敌人减少量最少

对于水平炮,我们这样建图:

即:假设$y$是$x$往炮方向的第一个点,如果$x$的敌人数量比炮能打到的最多敌人数量少$v$,那么连边$(x,y,v)$

对于竖直炮,我们这样建图:

即:假设$x$是$y$往炮方向的第一个点,如果$y$的敌人数量比炮能打到的最多敌人数量少$v$,那么连边$(x,y,v)$

对于这个图的竖边,如果我们割掉$(x,y,v)$,那么就相当于让某个竖直炮打$y$,并且它比最优情况打少了$v$个敌人,横边类似

如果我们把竖直炮设为源点,水平炮设为汇点,那么因为不能相交,所以我们割掉一些边(决定了某些炮的打击目标)后,不能有任何一条从源点到汇点的路径,所以就相当于求最小割

这样还会有一个问题:我们要割掉先走竖边再走横边(炮弹轨迹不能相交),但是交错走横竖边是被允许的,所以我们还要从(竖边连接的点)向对应的(横边连接的点)连一条$+\infty$的边,确保先走竖再走横的路径会被割掉

所以最后的答案就是每个炮能打到的最多敌人数量加起来再减去最小割

#include<stdio.h>
#include<string.h>
const int inf=2147483647;
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
int h[5010],cur[5010],nex[30010],to[30010],cap[30010],q[30010],dis[5010],M=1,S,T;
void add(int a,int b,int c){
	M++;
	to[M]=b;
	cap[M]=c;
	nex[M]=h[a];
	h[a]=M;
	M++;
	to[M]=a;
	cap[M]=0;
	nex[M]=h[b];
	h[b]=M;
}
bool bfs(){
	int x,i,head,tail;
	head=tail=1;
	q[1]=S;
	memset(dis,-1,sizeof(dis));
	dis[S]=0;
	while(head<=tail){
		x=q[head];
		head++;
		for(i=h[x];i;i=nex[i]){
			if(cap[i]&&dis[to[i]]==-1){
				dis[to[i]]=dis[x]+1;
				if(to[i]==T)return 1;
				tail++;
				q[tail]=to[i];
			}
		}
	}
	return 0;
}
int dfs(int x,int flow){
	if(x==T)return flow;
	int i,f;
	for(i=cur[x];i;i=nex[i]){
		if(cap[i]&&dis[to[i]]==dis[x]+1){
			f=dfs(to[i],min(flow,cap[i]));
			if(f){
				cap[i]-=f;
				cap[i^1]+=f;
				if(cap[i])cur[x]=i;
				return f;
			}
		}
	}
	dis[x]=-1;
	return 0;
}
int dicnic(){
	int ans=0,tmp;
	while(bfs()){
		memcpy(cur,h,sizeof(h));
		while(tmp=dfs(S,100000000))ans+=tmp;
	}
	return ans;
}
int n,m,s[60][60],tmp[60];
const int go[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool ok(int x,int y){return 0<x&&x<=n&&0<y&&y<=m;}
int ve(int x,int y){return(x-1)*m+y;}
int ho(int x,int y){return(x-1)*m+y+n*m;}
void move(int&x,int&y,int f){
	x+=go[f][0];
	y+=go[f][1];
}
int main(){
	int i,j,x,y,f,cnt,sum,mx;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++)scanf("%d",s[i]+j);
	}
	S=n*m*2+1;
	T=n*m*2+2;
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++)add(ve(i,j),ho(i,j),inf);
	}
	sum=0;
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			if(s[i][j]<0){
				x=i;
				y=j;
				f=-s[i][j]-1;
				cnt=0;
				while(ok(x,y)){
					cnt++;
					tmp[cnt]=max(tmp[cnt-1],s[x][y]);
					move(x,y,f);
				}
				mx=tmp[cnt];
				sum+=mx;
				move(x,y,f^1);
				while(x!=i||y!=j){
					cnt--;
					if(f<2)
						add(ve(x-go[f][0],y-go[f][1]),ve(x,y),mx-tmp[cnt]);
					else
						add(ho(x,y),ho(x-go[f][0],y-go[f][1]),mx-tmp[cnt]);
					move(x,y,f^1);
				}
				if(f<2)
					add(S,ve(i,j),inf);
				else
					add(ho(i,j),T,inf);
			}
		}
	}
	printf("%d",sum-dicnic());
}

[xsy2213]tower的更多相关文章

  1. Tower是个不错的项目管理开放平台

    简单,易用,轻量级,挺多大项目都在用. 目前公司的项目也在使用,但是从高层到底下,随意惯了,最终没有用起来. 感觉适合年轻激情的创业公司团队来使用. 附上地址:https://tower.im/

  2. dwarf tower

    dwarf tower(dwarf.cpp/c/pas)[问题描述]Vasya在玩一个叫做"Dwarf Tower"的游戏,这个游戏中有n个不同的物品,它们的编号为1到n.现在Va ...

  3. HDU1329 Hanoi Tower Troubles Again!——S.B.S.

    Hanoi Tower Troubles Again! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  4. ZOJ-1239 Hanoi Tower Troubles Again!

    链接:ZOJ1239 Hanoi Tower Troubles Again! Description People stopped moving discs from peg to peg after ...

  5. Ansible-Tower快速入门-6.查看tower的仪表板【翻译】

    查看tower的仪表板 到这一步,我们已经可以在屏幕上看到tower的仪表板了,我们可以看到你目前"主机""资产清单"和"项目"的汇总信息, ...

  6. 自动运维:Ansible -ansible tower

    文档主页:http://docs.ansible.com/参考文档:http://docs.ansible.com/ansible/参考文档:http://docs.ansible.com/ansib ...

  7. dp --- hdu 4939 : Stupid Tower Defense

    Stupid Tower Defense Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  8. 塔吊力矩限制器,塔吊黑匣子,塔吊电脑,tower crane

    塔机力矩限制器,tower crane 适用于各种类型的固定臂塔机和可变臂塔机 塔机力矩限制器是塔式起重机机械的安全保护装置,本产品采用32位高性能微处理器为硬件平台,软件算法采用国内最先进的三滑轮取 ...

  9. UVa 437 The Tower of Babylon(经典动态规划)

    传送门 Description Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details ...

随机推荐

  1. day06_06 字典操作01

    1.0 字典操作 dic1 = {'name':'alex'} dic1['age'] = 18 print(dic1) #>>>{'age': 18, 'name': 'alex' ...

  2. 孤荷凌寒自学python第五十五天初识MongoDb数据库

    孤荷凌寒自学python第五十五天第一天初识MongoDb数据库 (完整学习过程屏幕记录视频地址在文末) 大家好,2019年新年快乐! 本来我想的是借新年第一天开始,正式尝试学习爬虫,结果今天偶然发现 ...

  3. python使用工具简介介绍

    我从研究生开学以来就开始在学python,现在来简单分享下一些基本的使用命令和快捷方式 Pycharm: 运行程序 ctrl+alt+F10 删除一行ctrl+D 注释ctrl+/ 安装python所 ...

  4. 重现ssd遇到的问题

    首先是create_list.sh和create_data.sh中的data_dir的路径得修改. 然后是在create_data.sh文件调用$caffe_root下的scripts目录中的crea ...

  5. MySQL 主主同步

    双机热备的概念简单说一下,就是要保持两个数据库的状态自动同步.对任何一个数据库的操作都自动应用到另外一个数据库,始终保持两个数据库数据一致. 这样做的好处多. 1. 可以做灾备,其中一个坏了可以切换到 ...

  6. hexo 添加标签

    --- title: title #文章標題 date: 2016-06-01 23:47:44 #文章生成時間 categories: "Hexo教程" #文章分類目錄 可以省略 ...

  7. Struts1 生成Action请求的几种方式分析

    1 直接硬编码 <a href="/Lesson14_Struts1_Demo1//user/regUserDo.do">注册</a><br/> ...

  8. 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...

  9. js判断中出现两个!!是什么意思?

    在js中看源码时有时候出现两个!!,我起初以为是js的其他语法,其实!!就是两次取“非”的运算. 下面证明我的说法. alert(null);//false alert(!null);//true a ...

  10. java中截取字符串的方式

    1.length() 字符串的长度 例:char chars[]={'a','b'.'c'}; String s=new String(chars); int len=s.length(); 2.ch ...