2019-08-10 纪中NOIP模拟赛B组

家住魔仙堡 提交于 2019-11-26 20:21:57

T1 [JZOJ1235] 洪水

题目描述

  一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安全的。

  森林的地图由R行C列组成,空白区域用点“.”表示,洪水的区域用“*”表示,而岩石用“X”表示,另画家的住所用“D”表示,画家用“S”表示。

  有以下几点需要说明:

  1、 每一分钟画家能向四个方向移动一格(上、下、左、右)

  2、 每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)

  3、 洪水和画家都不能通过岩石区域

  4、 画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到的同时被洪水蔓延到了,这也是不允许的)

  5、 洪水蔓不到画家的住所

  给你森林的地图,编写程序输出最少需要花费多长时间才能从开始的位置赶回家中(如果画家不可能安全回家则输出“KAKTUS”)。

数据范围

  $2 \leq R,C \leq 50$

分析

  听说今天要加大难度,结果开局又是一道水题

  先 $BFS$ 预处理出每个区域最早被洪水蔓延的时间,再 $BFS$ 让画家把能走的路走一遍,如果能到达就输出最小步数,否则输出 $KAKTUS$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 55

int n, m, x0, y0, x1, y1;
int t[N][N], d[N][N], vis[N][N];
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
char g[N][N];

struct Point {
    int x, y;
} p;

bool check(int x, int y) {
    if (x < 1 || x > n) return false;
    if (y < 1 || y > m) return false;
    if (g[x][y] == 'X') return false;
    return true;
}

void bfs(int x, int y) {
    queue<Point> q;
    t[x][y] = 0;
    p.x = x; p.y = y; q.push(p);
    while (!q.empty()) {
        Point temp = q.front(); q.pop();
        for (int i = 0; i < 4; i++) {
            int dx = temp.x + dir[i][0];
            int dy = temp.y + dir[i][1];
            if (check(dx, dy) && g[dx][dy] != 'D')
                if (t[temp.x][temp.y] + 1 < t[dx][dy]) {
                    t[dx][dy] = t[temp.x][temp.y] + 1;
                    p.x = dx; p.y = dy; q.push(p);
                }
        }
    }
}

void BFS() {
    queue<Point> q;
    memset(d, 0x3f, sizeof d);
    d[x0][y0] = 0;
    p.x = x0; p.y = y0; q.push(p);
    while (!q.empty()) {
        Point temp = q.front(); q.pop();
        for (int i = 0; i < 4; i++) {
            int dx = temp.x + dir[i][0];
            int dy = temp.y + dir[i][1];
            if (check(dx, dy) && !vis[dx][dy])
                if (d[temp.x][temp.y] + 1 < t[dx][dy]) {
                    d[dx][dy] = d[temp.x][temp.y] + 1;
                    if (g[dx][dy] == 'D') return;
                    p.x = dx; p.y = dy; q.push(p);
                    vis[dx][dy] = 1;
                }
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            scanf(" %c", &g[i][j]);
            if (g[i][j] == 'S') x0 = i, y0 = j;
            if (g[i][j] == 'D') x1 = i, y1 = j;
        }
    memset(t, 0x3f, sizeof t);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (g[i][j] == '*') bfs(i, j);
    BFS();
    if (d[x1][y1] == inf) printf("KAKTUS\n");
    else printf("%d\n", d[x1][y1]);
    
    return 0;
}
View Code

 

T2 [JZOJ1236] 邦德I

题目描述

  每个人都知道詹姆斯邦德,著名的007,但很少有人知道很多任务都不是他亲自完成的,而是由他的堂弟们吉米邦德完成(他有很多堂弟),詹姆斯已经厌倦了把一个个任务分配给一个个吉米,他向你求助。

  每个月,詹姆斯都会收到一些任务,根据他以前执行任务的经验,他计算出了每个吉米完成每个任务的成功率,要求每个任务必须分配给不同的人去完成,每个人只能完成一个任务。

  请你编写程序找到一个分配方案使得所有任务都成功完成的最大概率。

数据范围

  $1 \leq N \leq 20$

分析

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!