连连看
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
小江最喜欢玩的游戏"天下3"最近推出了连连看的小玩法。玩家可以将2个相同图案的牌子连接起来,连接线不多于3根线段(即最多拐2折),就可以成功将这对牌子消除。如示意图所示,红色,黄色和蓝色的消除都是合法的,因为它们分别需要2个,0个和1个折。而黑色的消除是不合法的,因为这对牌至少需要拐3个折才能连接起来。
但是小江并不满足于这个游戏规则,因为他觉得最多只能拐2折这个限制并不合理。好奇的小江想知道的是,给定一个连连看的状态以及某一个牌子,在K折以内可以到达的所有具有相同图案的牌子的数量是多少。
输入
每个输入数据包含多个测试点。
第一行为测试点的个数S <= 20。之后是S个测试点的数据。
每个测试点的第一行为1 <= N <= 200, 1 <= M <= 200,表示连连看的大小。接下来的N行,每一行有M个整数,表示连连看该行的状态,如果为0,则表示该格为空,否则代表一种图案的牌子。
然后是三个整数X <= N, Y <= M,0 <= K <= 10000,表示查询(X, Y)这个牌子在K折以内能消除的所有相同牌子总数。其中连连看左上角的格子坐标为(1, 1),右下角为(N, M)。保证查询的格子是有图案的。
输出
对于每个测试点,输出对应的能消除的所有牌子总数。
提示
样例第一个例子,第(1, 1), (2, 3)和(2, 5)为3个可以在3折内被消除的相同牌子。
-
样例输入
-
3 4 5 1 0 1 0 2 0 0 1 3 1 3 3 1 5 9 6 1 4 8 7 1 3 3 4 5 1 0 1 0 2 0 0 1 3 1 3 3 1 5 9 6 1 4 8 7 1 3 1 2 2 1 10 2 3 1 1 10
样例输出
-
3 2 0
题目大意:最小转弯问题。(注意哪些是行哪些是列)
View Code
算法思路:
一种O(12nm)的算法,用dis[i][x][y]代表上一步走的是i方向,现处于(x, y)所需要的最小转弯数。用两个队列,一个记录探索到的道路,一个记录可以到达的目的点。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 import java.util.LinkedList; 2 import java.util.Queue; 3 import java.util.Scanner; 4 5 6 public class Main { 7 8 public static void main(String[] argv){ 9 Scanner in = new Scanner(System.in); 10 int x = in.nextInt(); 11 int y = in.nextInt(); 12 int [][] source = new int[x+2][y+2]; 13 int [][] R_has = new int[x+2][y+2]; 14 for(int i=1; i<=x;i++){ 15 for(int j=1; j<=y;j++){ 16 source[i][j]=in.nextInt(); 17 } 18 } 19 int a = in.nextInt(); 20 int b = in.nextInt(); 21 int c = in.nextInt(); 22 in.close(); 23 int Num = source[a][b]; 24 int[][][] dis = new int[4][x+2][y+2]; 25 Queue<Integer> temp = new LinkedList<Integer>(); 26 Queue<Integer> result = new LinkedList<Integer>(); 27 temp.offer(a); 28 temp.offer(b); 29 dis[0][a][b]=1; 30 dis[1][a][b]=1; 31 dis[2][a][b]=1; 32 dis[3][a][b]=1; 33 while(true){ 34 if(temp.size()==0) 35 break; 36 int N_x = temp.poll(); 37 int N_y = temp.poll(); 38 System.out.println("temp 出队:"+N_x+N_y+" 并开始匹配"); 39 //up adding 40 if(N_x-1>=0&&(source[N_x-1][N_y]==0||source[N_x-1][N_y]==Num)){ 41 42 System.out.println("up匹配: "); 43 int min=0; 44 if(dis[2][N_x][N_y]>0) 45 min=dis[2][N_x][N_y]; 46 if(dis[1][N_x][N_y]>0){ 47 if(min==0) 48 min=dis[1][N_x][N_y]+1; 49 else{ 50 if(dis[1][N_x][N_y]+1<min) 51 min=dis[1][N_x][N_y]+1; 52 } 53 } 54 if(dis[3][N_x][N_y]>0){ 55 if(min==0) 56 min=dis[3][N_x][N_y]+1; 57 else{ 58 if(dis[3][N_x][N_y]+1<min) 59 min=dis[3][N_x][N_y]+1; 60 } 61 } 62 if(min<=c){ 63 if(source[N_x-1][N_y]==0){ 64 int S_up=dis[2][N_x-1][N_y]; 65 dis[2][N_x-1][N_y]=min; 66 if( S_up!=min){ 67 System.out.println("temp 队列 add:"+(N_x-1)+" "+N_y); 68 temp.offer(N_x-1); 69 temp.offer(N_y); 70 } 71 72 } 73 else{ 74 if(R_has[N_x-1][N_y]==0){ 75 result.add(N_x-1); 76 result.add(N_y); 77 R_has[N_x-1][N_y]=1; 78 } 79 } 80 } 81 82 83 } 84 85 //down adding 86 if(N_x+1<x+2&&(source[N_x+1][N_y]==0||source[N_x+1][N_y]==Num)){ 87 88 System.out.println("down匹配: "); 89 int min=0; 90 if(dis[0][N_x][N_y]>0) 91 min=dis[0][N_x][N_y]; 92 if(dis[1][N_x][N_y]>0){ 93 if(min==0) 94 min=dis[1][N_x][N_y]+1; 95 else{ 96 if(dis[1][N_x][N_y]+1<min) 97 min=dis[1][N_x][N_y]+1; 98 } 99 } 100 if(dis[3][N_x][N_y]>0){ 101 if(min==0) 102 min=dis[3][N_x][N_y]+1; 103 else{ 104 if(dis[3][N_x][N_y]+1<min) 105 min=dis[3][N_x][N_y]+1; 106 } 107 } 108 if(min<=c){ 109 if(source[N_x+1][N_y]==0){ 110 int S_down=dis[0][N_x+1][N_y]; 111 dis[0][N_x+1][N_y]=min; 112 if(S_down!=min){ 113 System.out.println("temp 队列 add:"+(N_x+1)+" "+N_y); 114 temp.offer(N_x+1); 115 temp.offer(N_y); 116 } 117 118 } 119 else{ 120 if(R_has[N_x+1][N_y]==0){ 121 result.add(N_x+1); 122 result.add(N_y); 123 R_has[N_x+1][N_y]=1; 124 } 125 126 } 127 } 128 } 129 //right adding 130 if(N_y+1<y+2&&(source[N_x][N_y+1]==0||source[N_x][N_y+1]==Num)){ 131 132 System.out.println("right匹配: "); 133 int min=0; 134 if(dis[3][N_x][N_y]>0) 135 min=dis[3][N_x][N_y]; 136 if(dis[0][N_x][N_y]>0){ 137 if(min==0) 138 min=dis[0][N_x][N_y]+1; 139 else{ 140 if(dis[0][N_x][N_y]+1<min) 141 min=dis[0][N_x][N_y]+1; 142 } 143 } 144 if(dis[2][N_x][N_y]>0){ 145 if(min==0) 146 min=dis[2][N_x][N_y]+1; 147 else{ 148 if(dis[2][N_x][N_y]+1<min) 149 min=dis[2][N_x][N_y]+1; 150 } 151 } 152 //System.out.println("min: "+min); 153 if(min<=c){ 154 if(source[N_x][N_y+1]==0){ 155 int S_right=dis[3][N_x][N_y+1]; 156 dis[3][N_x][N_y+1]=min; 157 if(S_right!=min){ 158 System.out.println("temp 队列 add:"+N_x+" "+(N_y+1)); 159 temp.offer(N_x); 160 temp.offer(N_y+1); 161 } 162 163 } 164 else{ 165 if(R_has[N_x][N_y+1]==0){ 166 result.add(N_x); 167 result.add(N_y+1); 168 R_has[N_x][N_y+1]=1; 169 } 170 171 } 172 } 173 } 174 //left adding 175 if(N_y-1>=0&&(source[N_x][N_y-1]==0||source[N_x][N_y-1]==Num)){ 176 177 System.out.println("left匹配: "); 178 int min=0; 179 if(dis[1][N_x][N_y]>0) 180 min=dis[1][N_x][N_y]; 181 if(dis[0][N_x][N_y]>0){ 182 if(min==0) 183 min=dis[0][N_x][N_y]+1; 184 else{ 185 if(dis[0][N_x][N_y]+1<min) 186 min=dis[0][N_x][N_y]+1; 187 } 188 } 189 if(dis[2][N_x][N_y]>0){ 190 if(min==0) 191 min=dis[2][N_x][N_y]+1; 192 else{ 193 if(dis[2][N_x][N_y]+1<min) 194 min=dis[2][N_x][N_y]+1; 195 } 196 } 197 if(min<=c){ 198 if(source[N_x][N_y-1]==0){ 199 int S_left=dis[1][N_x][N_y-1]; 200 dis[1][N_x][N_y-1]=min; 201 if(S_left!=min){ 202 System.out.println("temp 队列 add:"+N_x+" "+(N_y-1)); 203 temp.offer(N_x); 204 temp.offer(N_y-1); 205 } 206 207 } 208 else{ 209 if(R_has[N_x][N_y-1]==0){ 210 result.add(N_x); 211 result.add(N_y-1); 212 R_has[N_x][N_y-1]=1; 213 } 214 215 } 216 217 } 218 } 219 System.out.println(""); 220 } 221 222 /* 223 for(Integer string : result){ 224 System.out.println(string); 225 } 226 */ 227 System.out.println("最终的结果: "+(result.size()-2)/2); 228 } 229 230 231 }