[NOI2007] 调兵遣将

news2025/2/1 20:00:59

题目描述

我军截获的情报显示,敌军正在集结兵力试图向我军重要的军械研究所发起进攻。由于我军正处于多线作战的状态,无法抽调大批兵力前去支援,指挥部决定通过有效的战前部署来提高胜率,减少伤亡和损失。

该军械研究所的平面图可以看作是一个 �×�N×M 的矩阵,每个1×11×1 的格子都表示一个区域,每个区域只与它上下左右的四个区域相邻。每个区域的用途可分为以下3 种之一:

1. 该区域被用于军事研究(用字母 O 表示);

2. 该区域内驻扎有一个机械化中队(用 # 表示);

3. 该区域是空地(用.表示)。

由于空间有限,任一个 1×11×1 的格子内都无法驻扎两队以上的机械化中队(包括两队),否则会大大降低战斗时的机动性。

遗憾的是,由于战前估计不足,我军的防御部署显得十分分散,这很容易让敌军所擅长的偷袭战术得逞。为了确保万无一失,我军决定利用为数不多的防御部队以最少的移动步骤将所有重要研究区域都包围起来。所谓的“包围”即从该矩阵边界侵入的敌军找不到任意一条路,使得他们不遭受任何机械化中队的反抗就能到达某研究区域。

由于军队内部的传令权限的限制,每个单位时间指挥部只能向所有中队中的一个中队下达指令(朝上/下/左/右移动 11 格)。由于时间紧迫,指挥部希望能够尽快完成部署,这个任务就交给你来完成。

注意:在部署的过程中军队可以进入研究区域,而在最终的部署结果中军队不可以在研究区域中。另外,在任何时刻,两个军队都不可以在同一个方格中。

输入格式

该题为提交答案型题目。

对于每个数据:

第一行 22 个整数 �N,�M,接下来 �N 行,每行包括 �M 个字符(.O或 #)。

输出格式

每个输出文件的第一行,包括你的答案所花费的时间 �T。

接下来 �T 行,按顺序输出每条命令,每行包括 44 个整数 �1,�1,�2,�2x1,y1,x2,y2,表示将位于 (�1,�1)(x1,y1) 的部队移向 (�2,�2)(x2,y2)。

输入输出样例

输入 #1复制

5 5
..##.
#...#
#OOO#
#..O#
.###.

输出 #1复制

1
2 1 2 2

说明/提示

如果选手的输出方案不合法(方案执行过程中出现军队重叠,军队移出矩形边界,最终方案有军队和研究所在同一区域,军队没有包围研究所等),则得零分,否则设选手输出的方案耗时为ans ,则得分按如下计算:

 

对于每个数据,都有两个评分参数 ��Ai​ 与 ��Bi​,其中保证 ��<��Ai​<Bi​。

#include<bits/stdc++.h>
#define int ll
using namespace std;
typedef long long ll;
const int N=105,N2=105,P=3*N*N2+5,M=1e7+5,inf=1e9;
char s[N][N2],ss[N][N2],tt[N][N2];
int n,m;
int fst[P],cur[P],nxt[M],u[M],v[M],flow[M],w[M],tot=1;
int que[P],dis[P],h,t,S=P-1,T=P-2;
int bk[P],vis[P];
int ch[N][N2];
int inq[P],a[P],pre[P];
queue<int> q;
int pp,qq;
bool dl[N][N2],Dl[N][N2];
void add(int lu,int lv,int lf,int lw=0)
{
	u[++tot]=lu,v[tot]=lv,flow[tot]=lf,w[tot]=lw,nxt[tot]=fst[lu],fst[lu]=tot;
	u[++tot]=lv,v[tot]=lu,flow[tot]=0,w[tot]=-lw,nxt[tot]=fst[lv],fst[lv]=tot;
}
int d(int r,int c,int id) {return (r-1)*m+c+n*m*id;}
bool bfs()
{
	memset(dis,0x3f,sizeof(dis)),dis[S]=0,que[h=t=1]=S;
	while(h<=t)
		for(int i=que[h++],j=fst[i];j;j=nxt[j])
			if(flow[j]&&dis[v[j]]>dis[i]+1) dis[v[j]]=dis[i]+1,que[++t]=v[j];
	return dis[T]<inf;
}
int dfs(int x,int lw,int tt=T)
{
	if(x==tt) return lw;
	int res=0,zl;
	for(int &i=cur[x];i;i=nxt[i])
		if(flow[i]&&dis[v[i]]==dis[x]+1&&(zl=dfs(v[i],min(lw,flow[i]),tt)))
		{
			lw-=zl,flow[i]-=zl,res+=zl,flow[i^1]+=zl;
			if(!lw) return res;
		}
	return res;
}
int dinic() {int res=0; while(bfs()) memcpy(cur,fst,sizeof(cur)),res+=dfs(S,inf); return res;}
void bfs(int x)
{
	bk[x]=1;
	for(int i=fst[x];i;i=nxt[i])
		if(!bk[v[i]]&&flow[i]) bfs(v[i]);
}
bool ade()
{
	int i,j;
	memset(fst,0,sizeof(fst)),tot=1;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
		{
			if(s[i][j]!='#'||dl[i][j]) add(d(i,j,0),d(i,j,1),s[i][j]!='O'? 1:inf);
			i<n&&(add(d(i,j,1),d(i+1,j,0),inf),add(d(i+1,j,1),d(i,j,0),inf),0),
			j<m&&(add(d(i,j,1),d(i,j+1,0),inf),add(d(i,j+1,1),d(i,j,0),inf),0),
			s[i][j]=='O'&&(add(S,d(i,j,0),inf),0);
		}
	for(i=1;i<=n;i++) add(d(i,1,1),T,inf),add(d(i,m,1),T,inf);
	for(i=2;i<m;i++) add(d(1,i,1),T,inf),add(d(n,i,1),T,inf);
	int R=dinic();
	if(R>=inf) return memset(fst,0,sizeof(fst)),tot=1,0;
	memset(bk,0,sizeof(bk)),bfs(S);
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			if(bk[d(i,j,0)]&&!bk[d(i,j,1)]) ch[i][j]=1;
			else ch[i][j]=0;
	memset(fst,0,sizeof(fst)),tot=1;
	return 1;
}
int vs[N][N];
void adeg(int r,int c,int sr,int sc)
{
	vs[r][c]=d(sr,sc,0);
	if(ch[r][c]) add(d(sr,sc,0),d(r,c,1),1,abs(sr-r)+abs(sc-c));
	if(abs(r-sr)+abs(c-sc)>10) return;
	if(c<m&&vs[r][c+1]!=d(sr,sc,0)) adeg(r,c+1,sr,sc);
	if(c>1&&vs[r][c-1]!=d(sr,sc,0)) adeg(r,c-1,sr,sc);
	if(r<n&&vs[r+1][c]!=d(sr,sc,0)) adeg(r+1,c,sr,sc);
	if(r>1&&vs[r-1][c]!=d(sr,sc,0)) adeg(r-1,c,sr,sc);
}
int res,ans=inf;
bool spfa()
{
	memset(dis,0x3f,sizeof(dis)),memset(inq,0,sizeof(inq)),q.push(S),dis[S]=0,inq[S]=1,a[S]=inf;
	while(!q.empty())
	{
		int x=q.front(); q.pop(),inq[x]=0;
		for(int i=fst[x];i;i=nxt[i])
			if(flow[i]&&dis[v[i]]>dis[x]+w[i])
				dis[v[i]]=dis[x]+w[i],pre[v[i]]=i,a[v[i]]=min(a[x],flow[i]),!inq[v[i]]&&(q.push(v[i]),inq[v[i]]=1);
	}
	if(dis[T]>inf) return 0;
	res+=dis[T]*a[T],pp+=a[T];
	for(int i=T;i!=S;i=u[pre[i]]) flow[pre[i]]-=a[T],flow[pre[i]^1]+=a[T];
	return 1;
}
int Cl;
struct aa
{
	int x1,y1,x2,y2;
}as[P];
stack<aa> st;
#define XX if(ss[x2][y2]=='#') while(!st.empty()) as[++Cl]=st.top(),st.pop();
void walk(int x1,int y1,int x2,int y2)
{
	if(x1==x2&&y1==y2) return;
	ss[x2][y2]='#';
	while(y2>y1) {st.push(aa{x2,y2-1,x2,y2}),y2--;XX}
	while(x2>x1) {st.push(aa{x2-1,y2,x2,y2}),x2--;XX}
	while(y2<y1) {st.push(aa{x2,y2+1,x2,y2}),y2++;XX}
	while(x2<x1) {st.push(aa{x2+1,y2,x2,y2}),x2++;XX}
	ss[x1][y1]='.';
}
void cal()
{
	int i,j,li;
	if(ade())
	{
		pp=qq=0;
		memset(vs,0,sizeof(vs));
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
				if(s[i][j]=='#'&&!ch[i][j]) adeg(i,j,i,j),add(S,d(i,j,0),1,0);
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
				if(ch[i][j]&&s[i][j]!='#') add(d(i,j,1),T,1,0),qq++;
		res=0;
		while(spfa());
		if(res<ans&&qq==pp)
		{
			ans=res,Cl=0;
			memcpy(ss,s,sizeof(ss));
			while(!st.empty()) st.pop();
			for(i=1;i<=n;i++)
				for(j=1;j<=m;j++)
					if(ss[i][j]=='#')
						for(li=fst[d(i,j,0)];li;li=nxt[li])
							if(!flow[li]&&v[li]!=S) walk(i,j,(v[li]-n*m-1)/m+1,(v[li]-n*m-1)%m+1);
			memcpy(tt,ss,sizeof(tt));
		}
	}
}
void gt()
{
	memset(dl,0,sizeof(dl)),cal();
	cerr<<ans<<'\n';
	for(int t=1000;t>1;t*=0.99)
	{
		memcpy(Dl,dl,sizeof(Dl));
		for(int i=1;i<=t;i++)
		{
			int la=rand()%n+1,lb=rand()%m+1;
			dl[la][lb]^=1;
		}
		int lp=ans;
		if(cal(),lp==ans) memcpy(dl,Dl,sizeof(dl));
		else cerr<<ans<<'\n';
	}
}
signed main()
{
	freopen("surround10.in","r",stdin);
	freopen("surround0.out","w",stdout);
	int i,j,li,lj;
	cin>>n>>m,srand(time(0));
	for(i=1;i<=n;i++) scanf("%s",s[i]+1);
	gt();
//	for(i=1,cout<<'\n';i<=n;i++,cout<<'\n')
//		for(j=1;j<=m;j++) cout<<tt[i][j];
	cout<<ans<<'\n';
	for(i=1;i<=Cl;i++) cout<<as[i].x1<<' '<<as[i].y1<<' '<<as[i].x2<<' '<<as[i].y2<<'\n';
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/631195.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全自学笔记+学习路线+就业规划(超详细)

每天都有新闻报道描述着新技术对人们的生活和工作方式带来的巨大乃至压倒性影响。与此同时有关网络攻击和数据泄露的头条新闻也是日益频繁。 攻击者可谓无处不在&#xff1a;企业外部充斥着黑客、有组织的犯罪团体以及民族国家网络间谍&#xff0c;他们的能力和蛮横程度正日渐…

如何使虚拟机自动生成ip地址

一. 打开虚拟机并登录账号进入命令行界面输入指令&#xff1a; vi /etc/sysconfig/network-scripts/ifcfg-ens33 通过指令进入到下面的界面当中 点击键盘输入 "i" 进入编辑模式将文件修改为 文件当中的 BOOTPROTO可以将ip地址定义为自动生成类型或者静态指定类型其中…

力扣 213. 打家劫舍 II

一、题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈&#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻…

高考后计算机人工智能大类专业的选择建议

随着GPT的出现&#xff0c;很多人开始质疑是否还需要学计算机专业&#xff0c;计算机专业是否会消失。 先给结论&#xff0c;不会&#xff01; 只是会产生分层&#xff0c;大体上是这样的&#xff1a; 核心代码部分还是需要人来写的&#xff0c;只要是代码方式出现的结果&#…

了解ASEMI代理英飞凌TLE6208-6G其功能和应用的综合指南

编辑-Z TLE6208-6G是一款高度集成、通用且高效的汽车半桥驱动器&#xff0c;由英飞凌设计。这种功能强大的设备专门设计用于满足汽车应用的苛刻要求&#xff0c;如控制直流电机、螺线管和电阻负载。在本文中&#xff0c;我们将深入研究TLE6208-6G的功能、优点和应用&#xff0…

【Spring MVC】这几种传参方式这么强大,让我爱不释手,赶快与我一起去领略吧 ! ! !

前言: 大家好,我是良辰丫,在上2一篇文章中我们已经初步认识了Spring MVC,并且学习了热部署的配置,今天我们将继续开始我们的Spring MVC的学习! ! !&#x1f48c;&#x1f48c;&#x1f48c; &#x1f9d1;个人主页&#xff1a;良辰针不戳 &#x1f4d6;所属专栏&#xff1a;jav…

JDK9~17+Springboot3 @Resource常见问题和解决方案

一、常见问题描述 因为JDK版本升级的改动&#xff0c;在Jdk9~17环境下&#xff0c;搭建Springboot项目&#xff0c;会出现原有Resource&#xff08;javax.annotation.Resource&#xff09;不存在的问题&#xff0c;导致项目从Jdk8迁移到高版本时遇到的问题 原因 你可能会问&…

TiDB亿级数据亚秒响应查询将MySql数据全量迁移到TiDB

目录 1 下载安装TiDB工具包1.1 检查最新版本1.2 下载tidb-toolkit 2 Dumpling导出数据2.1 Dumpling工具简介2.2 导出需要的权限2.3 创建用户并授权2.4 验证数据库2.5 导出sql文件2.6 查看导出文件 3 TiDB Lightning导入数据3.1 TiDB Lightning简介3.2 TiDB Lightning 整体架构3…

蓝桥杯【第14届国赛】Python B组

本题解仅代表个人观点&#xff0c;仅供参考&#xff0c;欢迎各位指正 A&#xff1a;弹珠堆放 【问题描述】 小蓝有 20230610 颗磁力弹珠&#xff0c;他对金字塔形状尤其感兴趣&#xff0c;如下图所示&#xff1a; 高度为 1 的金字塔需要 1 颗弹珠&#xff1b; 高度为 2 的金字…

【Jetpack】使用 Room 中的 Migration 升级数据库异常处理 ( 多个数据库版本的迁移 | fallbackToDestructiveMigration() 函数处理升级异常 )

文章目录 一、Room#Migration 迁移工具升级数据库二、多个数据库版本的迁移三、数据库异常处理 - RoomDatabase.Builder#fallbackToDestructiveMigration() 函数四、完整代码示例 一、Room#Migration 迁移工具升级数据库 Room Migration 数据库迁移工具 是 Android Jetpack Arc…

【AI实战营第二期】第三次作业——基于 RTMDet 的气球检测(包含数据集)

作业&#xff1a;基于 RTMDet 的气球检测 背景&#xff1a;熟悉目标检测和 MMDetection 常用自定义流程。 任务&#xff1a; 基于提供的 notebook&#xff0c;将 cat 数据集换成气球数据集; 按照视频中 notebook 步骤&#xff0c;可视化数据集和标签; 使用MMDetection算法库…

01_Linux字符设备驱动开发

目录 字符设备驱动简介 驱动模块的加载和卸载 字符设备注册与注销 实现设备的具体操作函数 添加LICENSE和作者信息 Linux设备号的组成 设备号的分配 chrdevbase字符设备驱动开发实验 创建VSCode工程 添加头文件路径 编写实验程序 C库文件操作基本函数 编写测试APP…

苹果Vision Pro正式发布,下一个iPhone诞生了?

在库克即将退休之际&#xff0c;苹果开启了下一个十年。 2023年6月6日&#xff0c;在苹果WWDC开发者大会上&#xff0c;苹果发布了15寸的MacBook Air&#xff0c;以及一众iOS 17、iPad OS 17、Mac OS等系统的更新。当我们觉得这些常规更新有点不痛不痒&#xff0c;甚至想大呼“…

​selenium中元素定位正确但是操作失败,6种解决办法全稿定

selenium中元素定位正确但是操作失败的原因无外乎以下4种&#xff1a; 一、页面没加载好 解决方法&#xff1a;添加等待方法&#xff0c;如&#xff1a; time.sleep() 二、页面提交需要等待给数据后台 解决方法&#xff1a;添加等待方法&#xff0c;如&#xff1a; time.sl…

一套完整的三甲医院医学影像科PACS系统源码

一、PACS系统概述&#xff1a; 基于VC MSSQL开发的一套三甲医院医学影像PACS系统源码&#xff0c;集成3D影像后处理技术和功能&#xff0c;包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等能满足影像科功能。 二、PAC…

C/C++ 作用域,生命周期,执行线程的概念

相互影响 在C中&#xff0c;对象的生命周期、作用域和执行线程是三个相互关联但又相对独立的概念。它们共同决定了对象在程序中的行为和状态。下面我将详细解释这三个概念以及它们之间的关系和互相影响。 生命周期&#xff1a;对象的生命周期是指从对象被创建&#xff08;构造…

Python暑假自律打卡学习班,免费,速来(2)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 很快就放暑假了&#xff0c;还有20多天吧&#xff01; 猫妹对这个暑假相当期待啊&#xff0c; 想想今年的五一劳动节有多火爆…

仙境传说RO:npc汉化方法

仙境传说RO&#xff1a;npc汉化方法 大家好我是艾西&#xff0c;在我们说了那么多期的教程中大家应该有发现游戏内很多都还是英文的&#xff0c;如果对于国内的玩家开展这个游戏可能有些不熟悉的小伙伴玩起来会有点难受&#xff0c;今天艾西跟大家分享下怎么汉化NPC等。 我们…

异常数据检测 | Python实现基于高斯概分布的异常数据检测

文章目录 文章概述模型描述源码分享学习小结参考资料文章概述 高斯分布也称为正态分布。它可以被用来进行异常值检测,不过我们首先要假设我们的数据是正态分布的。不过这个假设不能适应于所有数据集。但如果我们做了这种假设那么它将会有一种有效的方法来发现异常值。 模型描述…

多元分类预测 | Matlab人工蜂群算法(ABC)优化随机森林(RF)的分类预测,ABC-RF分类预测模型,多输入单输出模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab人工蜂群算法(ABC)优化随机森林(RF)的分类预测,ABC-RF分类预测模型,多输入单输出模型 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,…