camelot.cpp

来自「dd牛的usaco源代码!对学习算法」· C++ 代码 · 共 184 行

CPP
184
字号
/*
ID: dd.ener1
PROG: camelot
LANG: C++
*/
#include <cstdio>
#include <cstring>
using namespace std;

const long maxP=26*40+20;
const long maxR=26,maxC=40;
long R,C;//R<=40, C<=26
long kingx,kingy;
long knightx[maxP];
long knighty[maxP];
long k_num;
unsigned long g[maxR][maxC][maxR][maxC];
bool inque[maxR][maxC];
long best;

void input(){
	freopen("camelot.in","r",stdin);
	scanf("%d %d\n",&R,&C);
	scanf("%c %d\n",&kingx,&kingy);
	kingx-='A';
	kingy-=1;
	char c;
	long l;
	for(;;){
		for(;;){
			c=getchar();
			if(c!=' '&&c!='\n')break;
		}
		if(feof(stdin))return;
		scanf("%d",&l);
		knightx[k_num]=c-'A';
		knighty[k_num]=l-1;
		++k_num;
	}
}
template<class T>
class queue{
	private:
		long N;
		T* s;
		long beg,end;
	public:
		inline void init(){
			beg=end=0;
		}
		queue(long size):N(size),s(new T[size]){
			init();
		}
		inline void push(const T& item){
			s[end]=item;
			++end;
			if(end==N)end=0;
		}
		inline T pop(){
			T res=s[beg];
			++beg;
			if(beg==N)beg=0;
			return res;
		}
		inline bool empty(){
			return beg==end;
		}
};
struct item{
	item(){}
	item(long _x,long _y,long _dis):x(_x),y(_y),dis(_dis){}
	long x,y;
	long dis;
};
void DFS(long x,long y){
	static const long deltax[8]={1,1,-1,-1,2,2,-2,-2};
	static const long deltay[8]={2,-2,2,-2,1,-1,1,-1};
	static queue<item> que(R*C+1);
	que.init();
	memset(inque,0,sizeof(inque));
	for(long i=0;i<C;++i)
		for(long j=0;j<R;++j)
			g[x][y][i][j]=10000;
	g[x][y][x][y]=0;
	inque[x][y]=true;
	que.push(item(x,y,0));
	do{
		item now=que.pop();
		g[x][y][now.x][now.y]=now.dis;
		for(long k=0;k<8;++k){
			long newx=now.x+deltax[k];
			if(newx<0||newx>=C)continue;
			long newy=now.y+deltay[k];
			if(newy<0||newy>=R)continue;
			if(inque[newx][newy])continue;
			que.push(item(newx,newy,now.dis+1));
			inque[newx][newy]=true;
		}
	}while(!que.empty());
}
void DFS(){
	for(long i=0;i<C;++i)
		for(long j=0;j<R;++j)
			DFS(i,j);
}
struct point{
	point(){}
	point(long _x,long _y):x(_x),y(_y){}
	long x,y;
};
long abs(long x){
	return x<0?-x:x;
}
long dis(point carry){
	long x=abs(carry.x-kingx);
	long y=abs(carry.y-kingy);
	return x>y?x:y;
}
void update(long& x,const long y){
	if(x>y)x=y;
}
long solve(const point &gather,const point &carry,long k){
	long res=0;
	res-=g[gather.x][gather.y][knightx[k]][knighty[k]];
	res+=dis(carry);
	res+=g[gather.x][gather.y][carry.x][carry.y];
	res+=g[carry.x][carry.y][knightx[k]][knighty[k]];
	return res;
}
void solve(const point &gather){
	long res=0;
	for(long k=0;k<k_num;++k)
		res+=g[knightx[k]][knighty[k]][gather.x][gather.y];
	if(res>best)return;
	point carry;
	long bestdelta=100000000;
	for(carry.x=0;carry.x<C;++carry.x)
		for(carry.y=0;carry.y<R;++carry.y){
			if(dis(carry)>bestdelta)continue;
			for(long k=0;k<k_num;++k)
				update(bestdelta,solve(gather,carry,k));
		}
	update(best,res+=bestdelta);
}
point midknight(){
	long sumx=0,sumy=0;
	for(long k=0;k<k_num;++k){
		sumx+=knightx[k];
		sumy+=knightx[k];
	}
	return point(sumx/k_num,sumy/k_num);
}
void presolve(){
	point pre=midknight();
	solve(pre);
	pre.x=kingx;
	pre.y=kingy;
	solve(pre);
}
void solve(){
	if(k_num==0){
		best=0;
		return;
	}
	best=1000000000;
	presolve();
	point gather;
	for(gather.x=0;gather.x<C;++gather.x)
		for(gather.y=0;gather.y<R;++gather.y)
			solve(gather);
			
}
void output(){
	freopen("camelot.out","w",stdout);
	printf("%d\n",best);
}
int main(){
	input();
	DFS();
	solve();
	output();
	return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?