USACO06JAN The Grove

题目传送门

新技巧!


了解了个新东西:虚拟射线法

题目要求我们绕树林一圈,为了使我们的搜索能满足这个条件,可以任意找一棵树,在它的下方建一堵墙,将原图分为左右两半,搜索时不许过墙,最后把墙拆掉,将图的两部分合并就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#define LL long long
using namespace std;
LL read() {
    LL k = 0; char c = getchar();
    while(c < '0' || c > '9')
        c = getchar();
    while(c >= '0' && c <= '9')
        k = k * 10 + c -48, c = getchar();
    return k;
}
char read_c() {
    char c = getchar();
    while(c != '.' && c != '*' && c  != 'X')
        c = getchar();
    return c;
}
int mapp[1010][1010];
struct zzz {
    int x, y;
}q[100010]; int h = 1, t;
int fx[9] = {0, 1, 0, -1, 0, 1, 1, -1, -1},
    fy[9] = {0, 0, -1, 0, 1, 1, -1, 1, -1};
int n, m;
bool judge(int xx, int yy) {
    if(xx < 1 || xx > n || yy < 1 || yy > m) return 1;
    return 0;
}
int main() {
    //freopen("1.in", "r", stdin);
    n = read(), m = read();
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j) {
            char c = read_c();
            if(c == 'X') mapp[i][j] = -1;
            if(c == '*') q[++t].x = i, q[t].y = j, mapp[i][j] = 1;
        }
    srand(time(0));
    int rx = rand() % n + 1, ry = rand() % m + 1;
    while(!mapp[rx][ry]) rx = rand() % n + 1, ry = rand() % m + 1;
    for(int i = rx + 1; i <= n; ++i)	//建墙
        if(mapp[i][ry] != -1) mapp[i][ry] = -2;
    while(h <= t) {
        int x = q[h].x, y = q[h++].y;
        for(int i = 1; i <= 8; ++i) {
            int xx = x + fx[i], yy = y + fy[i];
            if(mapp[xx][yy] || judge(xx, yy)) continue;
            mapp[xx][yy] = mapp[x][y] + 1;
            q[++t].x = xx, q[t].y = yy;
        }
    }
    int ans = 2333;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            if(mapp[i][j] == -2) {	//拆墙+合并
                for(int k = -1; k <= 1; ++k)
                    for(int o = -1; o <= 1; ++o) {
                        int xx1 = i + k, xx2 = i + o;
                        if(mapp[xx1][j-1] == -1 || mapp[xx2][j+1] == -1 || judge(xx1, j-1) || judge(xx2, j+1) || !mapp[xx1][j-1] || !mapp[xx2][j+1])
                            continue;
                        ans = min(ans, mapp[xx1][j-1] + mapp[xx2][j+1]);
                    }
            }
    cout << ans << endl;
    return 0;
}
posted @ 2019-11-14 10:26  MorsLin  阅读(121)  评论(0)    收藏  举报