ZOJ-2411 link link look

来源:互联网 发布:有益网络 编辑:程序博客网 时间:2024/06/06 02:48


提交到ZOJ,WA了N次,终于修成正果^_^,排在第三位。 

我的思路是这样的:

从S和T分别如图扩展,如果扩展过程相遇,直接返回可以消去,否则还得像箭头那样扫描,如果同时扫过黄色和蓝色,返回可以消去。

当然,这些过程中还有许多细节,请参阅源代码。

补充一点,这个代码改一改就可以做成连连看的游戏,不过少了判断死锁的模块和生成新游戏的模块。

/* * ZOJ Problem Set - 2411 Link Link Look * Analysis: BFS * Author: mike-w */#include<stdio.h>#include<stdbool.h>#include<stdlib.h>#include<string.h>#define INPUT "input.txt"#define SIZE 100int grid[SIZE+2][SIZE+2];bool mark[SIZE+2][SIZE+2];/* * 我的一个思路是BFS,可惜我写不出来==! * 我的另一个思路是*&&^&$#$——一个说不清楚的办法... * 具体实现是从起点和终点开始向上下左右四个方向延伸标记 * 然后再用一条直线扫描 */int click(int x1,int y1,int x2,int y2,int maxx,int maxy){if(x1==x2&&y1==y2)return 0;if(grid[x1][y1]!=grid[x2][y2])/* 方块颜色不同 */return 0;if(!grid[x1][y1])/* 点击在空白处 */return 0;int rec1,rec2,rec3,rec4,i,j,v;memset(mark,0,sizeof(mark));mark[x1][y1]=mark[x2][y2]=1;v=grid[x1][y1];grid[x1][y1]=grid[x2][y2]=0;/* 从 (x1,y1) 开始探索 */for(i=1;x1+i<=maxx+1&&!grid[x1+i][y1];i++)/* 向下探索 */if(mark[x1+i][y1])return 2;else mark[x1+i][y1]=1;rec1=x1+i-1;for(i=1;x1-i>=0&&!grid[x1-i][y1];i++)/* 向上探索 */if(mark[x1-i][y1])return 2;else mark[x1-i][y1]=1;rec2=x1-i+1;for(i=1;y1+i<=maxy+1&&!grid[x1][y1+i];i++)/* 向右探索 */if(mark[x1][y1+i])return 2;else mark[x1][y1+i]=1;rec3=y1+i-1;for(i=1;y1-i>=0&&!grid[x1][y1-i];i++)/* 向左探索 */if(mark[x1][y1-i])return 2;else mark[x1][y1-i]=1;rec4=y1-i+1;/* 从终点 (x2,y2) 开始探索 */for(i=1;x2+i<=maxx+1&&!grid[x2+i][y2];i++)/* 向下探索 */if(mark[x2+i][y2])return 2;else mark[x2+i][y2]=1;for(i=1;x2-i>=0&&!grid[x2-i][y2];i++)/* 向上探索 */if(mark[x2-i][y2])return 2;else mark[x2-i][y2]=1;for(i=1;y2+i<=maxy+1&&!grid[x2][y2+i];i++)/* 向右探索 */if(mark[x2][y2+i])return 2;else mark[x2][y2+i]=1;for(i=1;y2-i>=0&&!grid[x2][y2-i];i++)/* 向左探索 */if(mark[x2][y2-i])return 2;else mark[x2][y2-i]=1;/* 开始“神奇地”扫描 */for(i=rec2;i<=rec1;i++)/* 水平扫描 */{if(i==x1)continue;for(j=1;y1+j<=maxy+1&&!grid[i][y1+j];j++)if(mark[i][y1+j])/*  这时已经不需要再标记了 */return 2;for(j=1;y1-j>=0&&!grid[i][y1-j];j++)if(mark[i][y1-j])return 2;}for(i=rec4;i<=rec3;i++)/* 垂直扫描 */{if(i==y1)continue;for(j=1;x1+j<=maxx+1&&!grid[x1+j][i];j++)if(mark[x1+j][i])return 2;for(j=1;x1-j>=0&&!grid[x1-j][i];j++)/* 其实这两个for只有一个做有用功 */if(mark[x1-j][i])return 2;}grid[x1][y1]=grid[x2][y2]=v;/* 恢复grid的值 */return 0;/* 消掉0个 */}int main(void){int nclick,n,m;int x1,x2,y1,y2,i,j;int dis=0;/*freopen(INPUT,"r",stdin);*/while(scanf("%d%d",&n,&m)!=EOF&&m&&n){dis=0;memset(grid,0,sizeof(grid));for(i=1;i<=n;i++)for(j=1;j<=m;j++)scanf("%d",grid[i]+j);scanf("%d",&nclick);while(nclick--){scanf("%d%d%d%d",&x1,&y1,&x2,&y2);dis+=click(x1,y1,x2,y2,n,m);/* click() 返回消去的方块数 */}printf("%d\n",dis);}return 0;}


 下面是第二个版本,做了一小点优化,不过还是20ms

/* * ZOJ Problem Set - 2411 Link Link Look * Analysis: BFS * Author: mike-w */#include<stdio.h>#include<stdbool.h>#include<stdlib.h>#include<string.h>#define INPUT "input.txt"#define SIZE 100int grid[SIZE+2][SIZE+2];bool mark[SIZE+2][SIZE+2];/* * 我的一个思路是BFS,可惜我写不出来==! * 我的另一个思路是*&&^&$#$——一个说不清楚的办法... * 具体实现是从起点和终点开始向上下左右四个方向延伸标记 * 然后再用一条直线扫描 */int click(int x1,int y1,int x2,int y2,int maxx,int maxy){if(x1==x2&&y1==y2)return 0;if(grid[x1][y1]!=grid[x2][y2])/* 方块颜色不同 */return 0;if(!grid[x1][y1])/* 点击在空白处 */return 0;int rec1,rec2,rec3,rec4,i,j,v;memset(mark,0,sizeof(mark));mark[x1][y1]=mark[x2][y2]=1;v=grid[x1][y1];grid[x1][y1]=grid[x2][y2]=0;/* 从 (x1,y1) 开始探索 */for(i=1;x1+i<=maxx+1&&!grid[x1+i][y1];i++)/* 向下探索 */if(mark[x1+i][y1])return 2;else mark[x1+i][y1]=1;rec1=x1+i-1;for(i=1;x1-i>=0&&!grid[x1-i][y1];i++)/* 向上探索 */if(mark[x1-i][y1])return 2;else mark[x1-i][y1]=1;rec2=x1-i+1;for(i=1;y1+i<=maxy+1&&!grid[x1][y1+i];i++)/* 向右探索 */if(mark[x1][y1+i])return 2;else mark[x1][y1+i]=1;rec3=y1+i-1;for(i=1;y1-i>=0&&!grid[x1][y1-i];i++)/* 向左探索 */if(mark[x1][y1-i])return 2;else mark[x1][y1-i]=1;rec4=y1-i+1;/* 从终点 (x2,y2) 开始探索 */for(i=1;x2+i<=maxx+1&&!grid[x2+i][y2];i++)/* 向下探索 */if(mark[x2+i][y2])return 2;else mark[x2+i][y2]=1;for(i=1;x2-i>=0&&!grid[x2-i][y2];i++)/* 向上探索 */if(mark[x2-i][y2])return 2;else mark[x2-i][y2]=1;for(i=1;y2+i<=maxy+1&&!grid[x2][y2+i];i++)/* 向右探索 */if(mark[x2][y2+i])return 2;else mark[x2][y2+i]=1;for(i=1;y2-i>=0&&!grid[x2][y2-i];i++)/* 向左探索 */if(mark[x2][y2-i])return 2;else mark[x2][y2-i]=1;/* 开始“神奇地”扫描 */for(i=rec2;i<=rec1;i++)/* 水平扫描 */{if(i==x1||y1==y2)continue;if(y2>y1){for(j=1;y1+j<=maxy+1&&!grid[i][y1+j];j++)if(mark[i][y1+j])/*  这时已经不需要再标记了 */return 2;}else{for(j=1;y1-j>=0&&!grid[i][y1-j];j++)if(mark[i][y1-j])return 2;}}for(i=rec4;i<=rec3;i++)/* 垂直扫描 */{if(i==y1||x1==x2)continue;if(x2>x1){for(j=1;x1+j<=maxx+1&&!grid[x1+j][i];j++)if(mark[x1+j][i])return 2;}else{for(j=1;x1-j>=0&&!grid[x1-j][i];j++)if(mark[x1-j][i])return 2;}}grid[x1][y1]=grid[x2][y2]=v;/* 恢复grid的值 */return 0;/* 消掉0个 */}int main(void){int nclick,n,m;int x1,x2,y1,y2,i,j;int dis=0;/*freopen(INPUT,"r",stdin);*/while(scanf("%d%d",&n,&m)!=EOF&&m&&n){dis=0;memset(grid,0,sizeof(grid));for(i=1;i<=n;i++)for(j=1;j<=m;j++)scanf("%d",grid[i]+j);scanf("%d",&nclick);while(nclick--){scanf("%d%d%d%d",&x1,&y1,&x2,&y2);dis+=click(x1,y1,x2,y2,n,m);/* click() 返回消去的方块数 */}printf("%d\n",dis);}return 0;}

原创粉丝点击