[NOIP2017TG] 小凯的疑惑

题意

  小凯有两种面值的金币,每种金币有无数个,求在无法准确支付的物品中,最贵的价值是多少金币。

分析

  设两种金币面值分别为 $a$ 和 $b \; (a<b)$ ,答案为 $x$,则有$$x \equiv ma \, (mod \; b) \; (1 \leq m \leq b-1)$$

  即$$x=ma+nb \; (1 \leq m \leq b-1)$$

  显然当 $n \geq 0$ 时 $x$ 可以用 $a,b$ 表示出来,不合题意

  因此当 $n=-1$ 时 $x$ 取得最大值,此时 $x=ma-b$

  显然当 $m=b-1$ 时 $x$ 最大,此时 $x=(b-1)a-b=ab-a-b$

  因此 $a,b$ 所表示不出的最大的数是 $ab-a-b$

[NOIP2017PJ] 棋盘

题意

  在一个棋盘上,棋盘上每一个格子可能是红色、黄色或没有颜色的。你可以向上下左右四个方向走,但所经过的格子必须是有颜色的。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 $1$ 个金币。

  另外, 你可以花费 $2$ 个金币使用魔法让下一个无色格子暂时变为你指定的颜色。但如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法;只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而你离开了这个暂时有颜色的格子后,这个格子恢复为无色。

  求从棋盘左上角到右下角(保证左上角格子有颜色),最少需要花费多少金币。

分析

  这题有很多种做法,看完题后我最先想到了 $BFS$

  于是从左上角格子开始向四个方向尝试扩展,同时要记录当前到达任意一个格子所需的最少金币。若扩展时可以使该块的值更优,则将该块的坐标与所需金币数放入队列。扩展的过程只需要分几种情况模拟:有色块至有色块(是否同色),有色块至无色块,无色块至有色块(是否同色)。为了避免很多不必要的重复,我将队列改为了按金币数排序的小根堆。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x7fffffff
#define N 105

struct Point {
    int x, y, z, c;
    bool operator< (Point rhs) const{
        return z > rhs.z;
    }
} p, t;

int n, m;
int g[N][N], f[N][N];
priority_queue<Point> q;
int nxt[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};

void bfs() {
    memset(f, 0x3f, sizeof f);
    p.x = 1; p.y = 1; p.z = 0;
    f[1][1] = 0;
    q.push(p);
    while (!q.empty()) {
         t = q.top(); q.pop();
         if (t.z > f[t.x][t.y]) continue;
         for (int i = 0; i < 4; i++) {
            int dx = t.x + nxt[i][0], dy = t.y + nxt[i][1];
            int nc = g[t.x][t.y], dc = g[dx][dy];
            if (dx < 1 || dx > n || dy < 1 || dy > n) continue;
            if (t.z > f[dx][dy]) continue;
            if (nc) {
                if (dc) {
                    if (nc == dc) {
                        if (t.z < f[dx][dy]){
                            p.x = dx; p.y = dy; p.z = t.z;
                            f[p.x][p.y] = p.z;
                            q.push(p);
                        }
                    }
                    else if (t.z + 1 < f[dx][dy]) {
                        p.x = dx; p.y = dy; p.z = t.z + 1;
                        f[p.x][p.y] = p.z;
                        q.push(p);
                    }
                }
                else if (t.z + 2 <= f[dx][dy]) {
                    p.x = dx; p.y = dy; p.z = t.z + 2; p.c = nc;
                    f[p.x][p.y] = p.z;
                    q.push(p);
                }
            }
            else if (dc) {
                if (t.c == dc) {
                    if (t.z < f[dx][dy]) {
                        p.x = dx; p.y = dy; p.z = t.z;
                        f[p.x][p.y] = p.z;
                        q.push(p);
                    }
                }
                else if (t.z + 1 < f[dx][dy]) {
                    p.x = dx; p.y = dy; p.z = t.z + 1;
                    f[p.x][p.y] = p.z;
                    q.push(p);
                }
            }
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int x, y, c;
        scanf("%d%d%d", &x, &y, &c);
        if (c) g[x][y] = 1;
        else g[x][y] = 2;
    }
    bfs();
    if (f[n][n] < 1061109567) printf("%d\n", f[n][n]);
    else printf("-1\n");

    return 0;
}
View Code

相关文章:

  • 2022-02-09
  • 2022-01-10
  • 2022-02-05
  • 2021-11-13
  • 2021-11-22
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-01-08
  • 2023-04-05
  • 2021-05-29
  • 2022-01-12
  • 2022-02-06
  • 2021-08-16
  • 2022-02-23
相关资源
相似解决方案