• ZOJ2411连连看(link link look)题解


    1 /*
    2 * ZJU2411.cpp
    3 *
    4 * Created on: 2011-3-27
    5 * Author: Administrator
    6 *
    7 * 题目分析:
    8 * 1. 异点同色之间才能消去
    9 * 2. 可以走界外
    10 *
    11 * 算法分析:
    12 * 1. 从一点出发向某个方向扩展直到不能再扩展,其他3个方向相同处理
    13 * 2. 如从某一点a出发扩展,若a点方向是0,那么接下去0和2方向不需要再扩展,因为父节点已经扩展过了
    14 * 3. 扩展是先入队,不标记,等出队时候再标记,因为存在以下可能:
    15 * 棋板如下:
    16 * 1)2)
    17 * 1)红 空
    18 * 2)空 空
    19 * 3)蓝 红
    20 * 搜索的方向次序是0(下),1(右),2(上),3(左)
    21 * 搜索的转次是1
    22 * 搜索的点是(1,1) -> (3, 2)
    23 * (1, 1)扩展出(2, 1), (1, 2)
    24 * (2, 1)扩展出(2, 2)
    25 * 假设已经标记,那么(1, 1) -> (1, 2) -> (2, 2) -> (3, 2)这条途径将被(1, 1) -> (2, 1) -> (2, 2)埋没
    26 */
    27
    28 #include <stdio.h>
    29 #include <stdlib.h>
    30 #include <memory.h>
    31 #include <queue>
    32
    33 using namespace std;
    34
    35 const int MAXN = 100 + 2;
    36
    37 struct Status {
    38 int m_x, m_y, m_c, m_d; // 行,列,转次,方向
    39 Status(int x, int y, int c, int d) : m_x(x), m_y(y), m_c(c), m_d(d) {}
    40 };
    41
    42 int g_dir[4][2] = {
    43 {1, 0}, //
    44 {0, 1}, //
    45 {-1, 0}, //
    46 {0, -1} //
    47 };
    48
    49 // 输入输出以及数组类型均定义为全局变量,命名规则,g_变量名,g_ans,g_数组名
    50 int g_maze[MAXN][MAXN], g_maze_tmp[MAXN][MAXN];
    51
    52 int g_N, g_M;
    53 int g_x1, g_y1, g_x2, g_y2;
    54 int g_T;
    55 int g_ans;
    56
    57 // 是否当前方向与扩展方向是否在一条线上
    58 inline bool is_linable(int orig_dir, int next_dir) {
    59 // 如果是初始点
    60 if (orig_dir == -1)
    61 return false; // 那么非线性
    62
    63 // 如果是同向有反向
    64 if (orig_dir == next_dir || 2 == abs(orig_dir - next_dir))
    65 return true; // 那么线性
    66
    67 return false; // 否则非线性
    68 }
    69
    70 // 是否下一个点可以到达
    71 inline bool is_reachable(int x, int y) { // (x, y)是否可达
    72 // 下个位置可行,可以到达界外
    73 if (x >= 0 && x <= g_N+1 && y >= 0 && y <= g_M+1 && 0 ==g_maze_tmp[x][y])
    74 return true;
    75
    76 return false; // 不可达
    77 }
    78
    79 // 是否已经达到目标点
    80 inline bool is_arrived(int x, int y) {
    81 if (x == g_x2 && y == g_y2)
    82 return true;
    83
    84 return false; //
    85 }
    86
    87 // 单纯的从(g_x1, g_y1) 搜索到一条2折内到(g_x2, g_y2)的路径
    88 bool special_bfs() {
    89 memcpy(g_maze_tmp, g_maze, sizeof(g_maze));
    90
    91 // 首先可以确定的是若是两次点击同一个点,虽然相同但是不能消去
    92 queue<Status> q;
    93 q.push(Status(g_x1, g_y1, -1, -1));
    94
    95 while (!q.empty()) {
    96 Status t = q.front();
    97 q.pop();
    98 g_maze_tmp[t.m_x][t.m_y] = -1; // 标记为不可达
    99
    100 for (int i = 0; i < 4; i++) { // 四个方向扩展,
    101 // 如果同向或者相向,那么不用扩展,因为父节点已经扩展过
    102 if (is_linable(t.m_d, i))
    103 continue;
    104
    105 // 下一个位置的行,列坐标,方向,转次
    106 int nx = t.m_x + g_dir[i][0];
    107 int ny = t.m_y + g_dir[i][1];
    108 int nd = i;
    109 int nc = t.m_c + 1;
    110
    111 // 如果下一个位置可达
    112 while (is_reachable(nx, ny)) {
    113 // 如果已经找到一条路径
    114 if (is_arrived(nx, ny))
    115 return true;
    116
    117 // 如果此点还有继续扩展能力
    118 if (nc < 2) // 因为下一次扩展肯定要转向,所以转次至少还剩1
    119 q.push(Status(nx, ny, nc, nd));
    120
    121 nx += g_dir[i][0];
    122 ny += g_dir[i][1];
    123 } // while
    124 } // for
    125 } // while
    126
    127 return false;
    128 }
    129
    130 int main() {
    131 while (EOF != scanf("%d %d", &g_N, &g_M)) {
    132 if (g_N == 0 && g_M == 0)
    133 break;
    134
    135 // 输入
    136 for (int i = 1; i <= g_N; i++)
    137 for (int j = 1; j <= g_M; j++)
    138 scanf("%d", g_maze[i] + j);
    139
    140 scanf("%d", &g_T);
    141 g_ans = 0;
    142 for (int i = 0; i < g_T; i++) {
    143 scanf("%d %d %d %d", &g_x1, &g_y1, &g_x2, &g_y2);
    144
    145 // 搜索前预判断
    146 // 如果有一点为空
    147 if (g_maze[g_x1][g_y1] == 0 || g_maze[g_x2][g_y2] == 0)
    148 continue;
    149 // 如果两点在同一点
    150 if (g_x1 == g_x2 && g_y1 == g_y2)
    151 continue;
    152 // 如果两点不一样
    153 if (g_maze[g_x1][g_y1] != g_maze[g_x2][g_y2])
    154 continue;
    155
    156 // 预处理
    157 int t = g_maze[g_x1][g_y1];
    158 g_maze[g_x1][g_y1] = 0;
    159 g_maze[g_x2][g_y2] = 0;
    160
    161 // 如果能联通,
    162 if (special_bfs())
    163 g_ans += 2;
    164 else { // 如果不能连同,则复原预处理
    165 g_maze[g_x1][g_y1] = t;
    166 g_maze[g_x2][g_y2] = t;
    167 }
    168 }
    169
    170 printf("%d\n", g_ans);
    171 }
    172 return 0;
    173 }
    174
    175 /*
    176 测试数据:
    177 3 4
    178 1 1 2 2
    179 3 3 4 4
    180 2 2 1 1
    181 6
    182 1 1 1 2
    183 1 3 1 4
    184 2 1 2 2
    185 2 3 2 4
    186 3 1 3 2
    187 3 3 3 4
    188
    189 3 4
    190 1 2 1 2
    191 3 4 3 4
    192 2 1 2 1
    193 7
    194 1 1 1 1
    195 1 1 1 2
    196 1 3 1 4
    197 2 1 2 2
    198 2 3 2 4
    199 3 1 3 2
    200 3 3 3 4
    201
    202 3 4
    203 1 2 1 2
    204 1 1 2 2
    205 2 2 1 1
    206 3
    207 2 3 2 4
    208 2 2 3 3
    209 3 2 1 4
    210
    211 2 3
    212 0 0 0
    213 0 0 0
    214 2
    215 1 1 1 1
    216 1 1 1 2
    217
    218 0 0
    219
    220 */
  • 相关阅读:
    国家行政区划地区编码表
    Java循环中标签的作用(转)
    通过ribbon 根据服务名获取所有服务实例的IP和端口列表
    rabbitmq重装依赖的erlang 要注意
    Rabbitmq关于集群节点功能的读书笔记
    CentOS7统计某个进程当前的线程数
    理解同步、异步、阻塞、非阻塞(传送门)
    代理模式和装饰模式区别
    【转载】Asp.Net生成图片验证码工具类
    【转载】使用宝塔Linux面板屏蔽某些IP访问你的服务器
  • 原文地址:https://www.cnblogs.com/nysanier/p/1996831.html
Copyright © 2020-2023  润新知