[NOI2007] 调兵遣将

题目描述

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

该军械研究所的平面图可以看作是一个 �×�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 ,则得分按如下计算:

[NOI2007] 调兵遣将_第1张图片

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

#include
#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 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) 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(c1&&vs[r][c-1]!=d(sr,sc,0)) adeg(r,c-1,sr,sc);
	if(r1&&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 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(y21;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<>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<

你可能感兴趣的:(c++简介,NOI题库,c++,开发语言,算法,数据结构)