D. Dasha and Chess
题意
给你999*999的棋盘,上面有666个士兵和一个国王,你来操纵国王,checker来操纵士兵,最初国王所在行和列没有任何士兵,每次你可以向你八连通方向任意一个格子移动,而士兵可以从一个地方到任何一个没有棋子的地方,你获胜的条件是你挪动之后,你所在的行或列有一个或多个士兵,交互题,提供2000次操作之后必胜的方法。
做法
这道题一定要仔细思考数据范围,首先我们将国王挪到中间,之后我们所面临的最差情况是这样的。
666个棋子被均分在四个角落,这时我们发现,如果我们向着一个角移动,那么对方要改变相应的三个角的棋子的位置,而最差情况下三个角的最大和是166+167+167=500.而我们只需要499步就可以挪动到边界,也就是说,我们只要向着三个方向加起来最大的那个角移动,必胜!
这道题实现起来有很多细节,在斜向移动的过程中要判断要移的方向上是否已经有棋子,如果已经有棋子,我们只需要挪动x或者y即可获得胜利。
代码
#include<stdio.h>
#include<stdlib.h>
const int maxn = 1005;
int x,y,u,v,w,px[maxn],py[maxn],vis[maxn][maxn],sum[5],sum2[5];
int dis[5][2]={
0,0,-1,-1,-1,1,1,-1,1,1};
void move_(int xx,int yy)
{
x+=xx;y+=yy;if(vis[x][y]) x-=xx;printf("%d %d\n",x,y);fflush(stdout);scanf("%d%d%d",&u,&v,&w);if(u==-1&&v==-1&&w==-1) exit(0);vis[px[u]][py[u]]=0;vis[v][w]=1;px[u]=v;py[u]=w;return ;
}
int main()
{
scanf("%d%d",&x,&y);for(int i=1;i<=666;i++){
scanf("%d%d",&px[i],&py[i]);vis[px[i]][py[i]]=1;}int dir=-1;while(x<500) move_(1,0);while(y<500) move_(0,1);while(x>500) move_(-1,0);while(y>500) move_(0,-1);for(int i=1;i<=499;i++) for(int j=1;j<=499;j++) if(vis[i][j]) sum[1]++;for(int i=1;i<=499;i++) for(int j=501;j<=999;j++) if(vis[i][j]) sum[2]++;for(int i=501;i<=999;i++) for(int j=1;j<=499;j++) if(vis[i][j]) sum[3]++;for(int i=501;i<=999;i++) for(int j=501;j<=999;j++) if(vis[i][j]) sum[4]++;sum2[1]=sum[1]+sum[2]+sum[3];sum2[2]=sum[2]+sum[1]+sum[4];sum2[3]=sum[3]+sum[1]+sum[4];sum2[4]=sum[4]+sum[2]+sum[3];int maxx=0;for(int i=1;i<=4;i++){
if(sum2[i]>maxx){
maxx=sum2[i];dir=i;}}while(true) move_(dis[dir][0],dis[dir][1]);return 0;
}