连连看 杭电1175

连连看

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 11866    Accepted Submission(s): 3115


Problem Description
“连连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。
玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。
 

 

Input
输入数据有多组。每组数据的第一行有两个正整数n,m(0<n<=1000,0<m<1000),分别表示棋盘的行数与列数。在接下来的n行中,每行有m个非负整数描述棋盘的方格分布。0表示这个位置没有棋子,正整数表示棋子的类型。接下来的一行是一个正整数q(0<q<50),表示下面有q次询问。在接下来的q行里,每行有四个正整数x1,y1,x2,y2,表示询问第x1行y1列的棋子与第x2行y2列的棋子能不能消去。n=0,m=0时,输入结束。
注意:询问之间无先后关系,都是针对当前状态的!
 

 

Output
每一组输入数据对应一行输出。如果能消去则输出"YES",不能则输出"NO"。
 

 

Sample Input
3 4
1 2 3 4
0 0 0 0
4 3 2 1
4
1 1 3 4
1 1 2 4
1 1 3 3
2 1 2 4
3 4
0 1 4 3
0 2 4 1
0 0 0 0
2
1 1 2 4
1 3 2 3
0 0
 

 

Sample Output
YES
NO
NO
NO
NO
YES
 
解题思路:
    题目要求是少于 2 次转折,并非最短路,所以单纯的广搜,最终会导致 WA,原因在于如果你走最短路走到了,但转折次数多余两次,不合要求,继续寻找,找到一条长的,转折次数不大于 2 次的路,但经过了走最短路时已标记的点,就会导致走不了,而错过正确答案!
    解决办法就是不标记路径而标记转折次数!
 
解题代码及注释:
View Code
  1 // File Name: /media/文档/源程序/实验室/4B广搜.cpp
  2 // Author: sheng
  3 // Created Time: 2013年03月15日 星期五 19时17分15秒
  4 
  5 #include <iostream>
  6 #include <string.h>
  7 using namespace std;
  8 typedef long long LL;
  9 # define Max 1005
 10 
 11 int n, m, x1, y1, x2, y2;
 12 int tag[Max][Max];
 13 LL map[Max][Max];
 14 
 15 struct node
 16 {
 17     int x;
 18     int y;
 19     int s;
 20     int sign;
 21 }Link[Max * Max+1];
 22 
 23 const int x_change[] = {0, 0, -1, 1};
 24 const int y_change[] = {1, -1, 0, 0};
 25 
 26 int bfs()
 27 {
 28     int rear, top, S;
 29     rear = top = S = 0;
 30     int X, Y, sign, sign1;
 31     Link[rear ++] = (node){x1, y1, S, -1};
 32 
 33     while(rear > top)
 34     {
 35         if (Link[top].x == x2 && Link[top].y == y2)///当到达终点时返回真值1
 36             return 1;
 37 
 38         X = Link[top].x;
 39         Y = Link[top].y;
 40         S = Link[top].s;
 41         sign = Link[top++].sign;
 42         for (int i = 0; i < 4; i ++)
 43         {
 44             int xx = X + x_change[i];
 45             int yy = Y + y_change[i];
 46             if(sign != i && sign != -1)///记录转折的方向,当前方向与之前的方向不同时,标记转折的结构体加一
 47             {        
 48                 Link[rear].s = S + 1;
 49             }
 50             else
 51             {
 52                 Link[rear].s = S;
 53             }
 54             ///判断元素坐标是否出界,转角次数是否超出规则
 55             if (xx >= n || yy >= m || xx < 0 || yy < 0 || Link[rear].s > 2)
 56                 continue;
 57             ///当前点有元素,但不是终点是继续循环
 58             if ( map[xx][yy] && !(xx == x2 && yy == y2))
 59                 continue 60             ///通过比较转折次数来控制是否能走,而不用标记
 61             if (tag[xx][yy] > Link[rear].s)
 62             {/////当再次回到该点时,由于转折次数不断累加,就会超出2的限制,则此点将不再进入队列
 63                 tag[xx][yy] = Link[rear].s;
 64                 Link[rear].x = xx;
 65                 Link[rear].y = yy;
 66                 Link[rear++].sign = i;
 67             }
 68         }
 69     }
 70     return 0;
 71 }
 72 
 73 int main ()
 74 {
 75     int t, i, j;
 76     while (cin >> n >> m)
 77     {
 78     
 79         if( !n && !m)
 80             break;
 81         for (i = 0; i < n; i ++)
 82         {
 83             for (j = 0; j < m; j ++)
 84                 cin >> map[i][j];
 85         }
 86         cin >> t;
 87         while (t--)
 88         {
 89             cin >> x1 >> y1 >> x2 >> y2;
 90             x1 = x1 - 1;
 91             y1 = y1 - 1;
 92             x2 = x2 - 1;
 93             y2 = y2 - 1;
 94             for (i = 0; i < n; i ++)
 95             {
 96                 for (j = 0; j < m; j ++)
 97                     tag[i][j] = 1000; ////使转折次数最大
 98             }
 99             ///当元素不等时,元素为 0 时, 起始处与终点处坐标相等时,直接输出 NO ,剪掉这一快
100             if (map[x1][y1] != map[x2][y2] || !map[x1][y1] || !map[x2][y2] || (x1 == x2 && y1 ==y2))
101                 cout <<"NO"<<endl;
102             else if(bfs())
103                 cout << "YES" << endl;
104             else  cout << "NO" << endl;
105         }
106     }
107     return 0;
108 }

 

改正之前的代码:

View Code
  1 // File Name: /media/文档/源程序/实验室/4B广搜.cpp
  2 // Author: sheng
  3 // Created Time: 2013年03月15日 星期五 19时17分15秒
  4 
  5 #include <iostream>
  6 #include <string.h>
  7 using namespace std;
  8 typedef long long LL;
  9 # define Max 1005
 10 
 11 int n, m, x1, y1, x2, y2;
 12 int tag[Max][Max];
 13 LL map[Max][Max];
 14 
 15 struct node
 16 {
 17     int x;
 18     int y;
 19     int s;
 20     int sign;
 21 }Link[Max * Max+1];
 22 
 23 const int x_change[] = {0, 0, -1, 1};
 24 const int y_change[] = {1, -1, 0, 0};
 25 
 26 int bfs()
 27 {
 28     int rear, top, S;
 29     rear = top = S = 0;
 30     int X, Y, sign, sign1;
 31     Link[rear ++] = (node){x1, y1, S, 0};
 32 
 33     while(rear > top)
 34     {
 35         /*
 36         cout<<"                       "<< Link[top].sign<< "      "<<Link[top].s<<endl;
 37         cout<<"                rear = "<<rear<<"      top = "<<top<<endl;
 38         cout<<"                Link[top].x = "<<Link[top].x<<"   Link[top].y = "<<Link[top].y<<endl;
 39         */
 40         if (Link[top].x == x2 && Link[top].y == y2 && Link[top].s <= 2)
 41             return 1;
 42 
 43         X = Link[top].x;
 44         Y = Link[top].y;
 45         S = Link[top].s;
 46         sign = Link[top++].sign;
 47         for (int i = 0; i < 4; i ++)
 48         {
 49             int xx = X + x_change[i];
 50             int yy = Y + y_change[i];
 51             if (xx >= n || yy >= m || xx < 0 || yy < 0)
 52                 continue;
 53             if ( (!map[xx][yy] || (xx == x2 && yy == y2)) && !tag[xx][yy])
 54             {
 55                 switch(i)
 56                 {
 57                     case 0: sign1 = 1;
 58                         break;
 59                     case 1: sign1 = 2;
 60                         break;
 61                     case 2: sign1 = 3;
 62                         break;
 63                     case 3: sign1 = 4;
 64                         break;
 65                 }
 66                 tag[xx][yy] = 1;
 67                 Link[rear].x = xx;
 68                 Link[rear].y = yy;
 69                 Link[rear].sign = sign1;
 70                 if(sign != sign1 && sign)
 71                 {        
 72                         Link[rear].s = S + 1;
 73                 }
 74                 else
 75                 {
 76                     Link[rear].s = S;
 77                 }
 78                 rear ++;
 79             }
 80         }
 81     }
 82     return 0;
 83 }
 84 
 85 int main ()
 86 {
 87     int t, i, j;
 88     while (cin >> n >> m)
 89     {
 90     
 91         if( !n || !m)
 92             break;
 93         for (i = 0; i < n; i ++)
 94         {
 95             for (j = 0; j < m; j ++)
 96                 cin >> map[i][j];
 97         }
 98         cin >> t;
 99         while (t--)
100         {
101             cin >> x1 >> y1 >> x2 >> y2;
102             x1 = x1 - 1;
103             y1 = y1 - 1;
104             x2 = x2 - 1;
105             y2 = y2 - 1;
106             memset(tag, 0 ,sizeof (tag));
107             if(map[x1][y1] == map[x2][y2] && map[x1][y1] && map[x2][y2])
108             {
109                 if(bfs())
110                     cout << "YES" << endl;
111                 else  cout << "NO" << endl;
112             }
113             else cout << "NO" << endl;
114         }
115     }
116     return 0;
117 }

 

 

posted on 2013-03-19 20:56  圣手摘星  阅读(202)  评论(0编辑  收藏  举报

导航