Problem solving [CTSC2002] Toy Soldier

Posted by locomotive on Wed, 12 Jan 2022 09:37:18 +0100

Let's discuss the problem separately from the three units

Cavalry and infantry: because one super ability can be changed at any time, it is easy to think of going to the third stage for an infantry i i For i points, the number of times they use super ability should be the shortest path problem from ( x 1 , y 1 ) (x_1,y_1) (x1, y1) go to ( x 2 , y 2 ) (x_2,y_2) (x2, y2) if h x 1 , y 1 < h x 2 , y 2 h_{x_1,y_1}<h_{x_2,y_2} hx1, y1 < hx2, y2 , then the edge weight is 1 1 1 (just find a cavalry super ability), otherwise the edge right is 0 0 0 The same goes for cavalry.

Tianbing: a proper tool man. Because there is no restriction on non super ability movement, Tianbing can run around, run to the target point, and then change an infantry or cavalry to the next point.

Then, due to the number of super abilities required for the two-point answer of the routine, let's say the second i i i soldiers to No j j If the number of superpowers used by j target points is greater than two points, it doesn't matter (you can't control it, either). Then the rest of the information can be obtained. We hope to make other arms point as many as possible without using celestial soldiers. Obviously, we can run the maximum matching of the bipartite graph once (Note: a target point can have at most two points) r i r_i When a soldier is there and encounters something that cannot be handled by conventional methods, we need to dismantle a point. We divide a target point into two r i r_i ri # target points and then run the maximum matching. In the shortest circuit, it should be noted that the original diagram is run, and then to the second i i The shortest path of i points to update the removed r i r_i ri (points).

Then we can only use the heavenly soldiers to transmit the unmatched soldiers. At this time, the point limit is meaningless. The heavenly soldiers can fly at will. So the number of times we use superpowers is 2 k − a n s 2k-ans 2k−ans ( a n s ans ans represents the maximum number of matches), and then follow this value with m i d mid mid can be compared.

Code (ugly, only for shooting)

#include<bits/stdc++.h>
using namespace std;
int n,m,k,t,s,vis[2005][2005],dis[2005][2005],h[505][505],d[2005][2005],tot;
int ssh(int x,int y){
	return (x-1)*m+y;
}
vector<int>G[200];
struct troop{
	int num,x,y;
}tp[206],re[206],R[206];
struct node{
	int x,y;
};  
struct qqq{
	int y,next;
	int used;
}a[5001],fc[500];
const int dx[]={-1,1,0,0};
const int dy[]={0,0,1,-1};
void BFS(int sx,int sy,bool M){
	queue<node>q;
	memset(vis,0,sizeof(vis));
	memset(dis,0x3f,sizeof(dis));
	dis[sx][sy]=0;
	q.push((node){sx,sy});
	while(!q.empty()){
		node top=q.front();
		q.pop();
		vis[top.x][top.y]=0;
		for(int i=0;i<4;i++){
			int ex=top.x+dx[i];
			int ey=top.y+dy[i];
			if(ex<1||ex>n||ey<1||ey>m)
			continue;
			int ds=0;
			int tmp=((dis[top.x][top.y]&1)^M);
			if(h[ex][ey]>h[top.x][top.y]&&tmp){
				ds=1;
			}
			if((h[ex][ey]<h[top.x][top.y]&&!tmp)){
				ds=1;
			}
			if(dis[top.x][top.y]+ds<dis[ex][ey]){
				dis[ex][ey]=dis[top.x][top.y]+ds;
				if(!vis[ex][ey]){ 
					q.push((node){ex,ey});
					vis[ex][ey]=1;
				}
			}
		}
	}
}
int match[200],vs[200];
int dfs(int u){
	for(int i=0;i<G[u].size();i++){
		int y=G[u][i];
		if(!vs[y]){
			vs[y]=1;
			if(!match[y]||dfs(match[y])){
				match[y]=u;
				return 1;				
			}
		}
	}
	return 0;
}
bool check(int mid){
	for(int i=0;i<=2*k;i++){
		G[i].clear();
	}
	memset(match,0,sizeof(match));
	for(int i=1;i<=2*k;i++){
		for(int j=1;j<=tot;j++){
			if(d[i][j]<=mid){
				//add(i,j);
				G[i].push_back(j);
			} 
		}
	}
	int ans=0;
	for(int i=1;i<=2*k;i++){
		memset(vs,0,sizeof(vs));
		ans+=dfs(i);
	}
	return ans+mid>=2*k;
	
}
int main()
{
	ios::sync_with_stdio(0);
	cin>>n>>m>>k>>t;
	tot=0;
	for(int i=1;i<=2*k+1;i++){
		cin>>tp[i].x>>tp[i].y;
	}
	for(int i=1;i<=t;i++){
		cin>>re[i].x>>re[i].y>>re[i].num;
		while(re[i].num--){
			R[++tot].x=re[i].x;
			R[tot].y=re[i].y;
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>h[i][j];
		}
	}
	for(int i=1;i<=2*k;i++){
		BFS(tp[i].x,tp[i].y,i>k);
		for(int j=1;j<=tot;j++){
			d[i][j]=dis[R[j].x][R[j].y];
		}	
	}
	int L=0,rR=2*k;
	while(L<rR){
		int mid=(L+rR)/2;
		if(check(mid))
		rR=mid;
		else
		L=mid+1;
	} 
	cout<<L<<endl;
   return 0;
}

Topics: Algorithm