UVa1321/LA2925 Dice contest

UVa1321/LA2925 Dice contest

题目链接

本题是2003年icpc欧洲区域赛中欧赛区D

题意

骰子的六面展开图如下,现在把骰子的六个面赋予一套权重 w i ( 1 ≤ w i ≤ 50 , 1 ≤ i ≤ 6 ) w_i(1\le w_i \le 50,1\le i\le 6) wi(1≤wi≤50,1≤i≤6),每翻转一次骰子的代价是翻转转后顶面的权重。

有一个4行无数列的网格桌子,初始时骰子顶面是1点,正面是2点(面向玩家),放置在 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)格子处,每次可以将骰子翻转到上下左右之一的相邻格子,翻转的代价是反转后顶面的权重,求将骰子翻转到 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)格子处的最小代价 ( − 1000000000 ≤ x 1 , x 2 ≤ 1000000000 , 1 ≤ y 1 , y 2 ≤ 4 ) (-1000000000\le x_1,x_2\le 1000000000,1\le y_1,y_2\le 4) (−1000000000≤x1,x2≤1000000000,1≤y1,y2≤4)。

分析

题意倒是好理解,但是题目的sample数据和uDebug上标程的输出不一致,巨坑。

1 2 3 8 1 4

-1 1 0 2

题目说sample输出是7,然而标程输出是5,反而下面这个数据标程才是输出7。

1 2 8 3 1 4

-1 1 0 2

这其实就是行从上到下还是从下到上编号的区别,如下图所示。

可见行从下往上是sample的输出是7,行从上往下输出是5(和标程相同),因此采用行从上往下处理。

骰子不管在哪个网格,有24种状态,乘上行数4,总共96,起点到终点的横坐标跨度 d x dx dx可能很大,考虑稀疏表/倍增法可将复杂度优化到 O ( 9 6 3 log ⁡ d x ) O(96^3\log dx) O(963logdx)(不超过 3 × 1 0 7 ) 3\times 10^7) 3×107):记 a [ y 1 ] [ s 1 ] [ y 2 ] [ s 2 ] [ i ] a[y_1][s_1][y_2][s_2][i] a[y1][s1][y2][s2][i]表示骰子在第 y 1 y_1 y1行状态为 s 1 s_1 s1,翻转到第 y 2 y_2 y2行状态为 s 2 s_2 s2且横向移动量为 2 i 2^i 2i( 1 ≤ y 1 , y 2 ≤ 4 , 0 ≤ s 1 , s 2 < 24 , 0 ≤ i < 31 1\le y_1,y_2\le 4,0\le s_1,s_2<24,0\le i<31 1≤y1,y2≤4,0≤s1,s2<24,0≤i<31)的最小代价。

这就需要求出初始横向移动量为1的最小代价 a [ y 1 ] [ s 1 ] [ y 2 ] [ s 2 ] [ 0 ] a[y_1][s_1][y_2][s_2][0] a[y1][s1][y2][s2][0],考虑到向右(或者向左)移动量为1的最小代价可能通过反方向移动更大的量再翻转回来(或者从其它行移动更大的量再翻转回来)而取得,如果横向移动动范围的极限能分析出来,并且极限比较小,则可以利用Dijkstra求得。

一个感性的结论是:横向移动范围的极限是19(向左/向右9,加上0),因为绕骰子三条轴任意一条翻转的不同权重最多也就4种并且顺/逆时针连续翻转以4为周期,如果绕某轴顺/逆时针净翻转(有可能顺时针翻转了2次逆时针翻又转回来一次,最终顺时针净翻转了一次)了4次以上最终横向移动量达到1,完全可以净翻转少于4次达到同样的结果并且代价更小,三条不同轴总共最多净翻转9次,即便全部贡献给横向移动(纵向移动也可能占用净翻转),向左/向右的最大移动量也才9。

因此确实可以用Dijkstra求出初始横向移动量为1的最小代价:记 d [ y 1 ] [ s 1 ] [ y 2 ] [ s 2 ] [ l ] d[y_1][s_1][y_2][s_2][l] d[y1][s1][y2][s2][l]表示骰子在第 y 1 y_1 y1行状态为 s 1 s_1 s1,翻转到第 y 2 y_2 y2行状态为 s 2 s_2 s2且横向移动量为 l l l的当前最小代价( 1 ≤ y 1 , y 2 ≤ 4 , 0 ≤ s 1 , s 2 < 24 , 0 ≤ l < 19 1\le y_1,y_2\le 4,0\le s_1,s_2< 24,0\le l< 19 1≤y1,y2≤4,0≤s1,s2<24,0≤l<19,如果横向移动量是负数 x x x,则用 19 + x 19+x 19+x来替代),对每个出发结点 ( y 1 , s 1 ) (y_1,s_1) (y1,s1),将其和初始值 d [ y 1 ] [ s 1 ] [ y 1 ] [ s 1 ] [ 0 ] = 0 d[y_1][s_1][y_1][s_1][0]=0 d[y1][s1][y1][s1][0]=0入优先级队列跑一遍Dijkstra,最终 d [ y 1 ] [ s 1 ] [ y 2 ] [ s 2 ] [ 1 ] d[y_1][s_1][y_2][s_2][1] d[y1][s1][y2][s2][1]就是所求。

测试数据

给一份CERC 2003官方的整套题解和测试数据。

AC 代码

cpp 复制代码
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

#define L 19
long long d[4][24][4][24][L], a[4][24][4][24][31], e[2][4][24]; bool f[4][24][L];
int c[][2] = {{2, 3}, {6, 3}, {6, 5}, {6, 2}, {6, 4}, {2, 4}}, w[7], x1, y1, x2, y2;

struct node {
    int y, s, x; long long d;
    bool operator< (const node &rhs) const {
        return d > rhs.d;
    }
} t;

int encode(int t, int f) {
    --t;
    return (t<<2) + (f == c[t][0] ? 0 : (f == c[t][1] ? 1 : (f == 7-c[t][0] ? 2 : 3)));
}

void decode(int s, int &t, int &f) {
    t = s>>2; f = s&3; f = f < 2 ? c[t++][f] : 7-c[t++][f-2];
}

void roll(int s, int d, int &t, int &f) {
    int t0, f0; decode(s, t0, f0); int (&e)[2] = c[t0-1];
    if (d == 0) t = f0, f = 7-t0;
    else if (d == 1) t = 7-f0, f = t0;
    else if (d == 2) t = f0 == e[0] ? 7-e[1] : (f0 == e[1] ? e[0] : (f0 == 7-e[0] ? e[1] : 7-e[0])), f = f0;
    else t = f0 == e[0] ? e[1] : (f0 == e[1] ? 7-e[0] : (f0 == 7-e[0] ? 7-e[1] : e[0])), f = f0;
}

long long solve() {
    for (int i=1; i<7; ++i) cin >> w[i];
    cin >> x1 >> y1 >> x2 >> y2; x2 -= x1; --y1; --y2;
    priority_queue<node> q; memset(d, 1, sizeof(d));
    for (int i=0; i<4; ++i) for (int j=0; j<24; ++j) {
        long long (&r)[4][24][L] = d[i][j]; q.push({i, j, 0, r[i][j][0] = 0}); memset(f, 0, sizeof(f));
        while (!q.empty()) {
            t = q.top(); q.pop(); int y = t.y, s = t.s, x = t.x > (L>>1) ? t.x-L : t.x; long long d = t.d;
            if (f[y][t.x][s]) continue;
            f[y][t.x][s] = true;
            for (int k=0; k<4; ++k) {
                int u = k<2 ? (k ? y-1 : y+1) : y, v = k<2 ? x : (k>2 ? x+1 : x-1), t, f, g; roll(s, k, t, f);
                if (u<0 || u>3 || abs(v) > (L>>1)) continue;
                if (v < 0) v += L;
                if (d + w[t] < r[u][g = encode(t, f)][v]) q.push({u, g, v, r[u][g][v] = d + w[t]});
            }
        }
    }
    for (int y=0; y<4; ++y) for (int s=0; s<24; ++s) e[0][y][s] = d[y1][0][y][s][0];
    int b = x2<0 ? L-1 : 1, k = 0, c = 0; x2 = abs(x2); memset(a, 1, sizeof(a));
    for (unsigned int i=x2; (1<<k) <= i; ++k);
    for (int y=0; y<4; ++y) for (int s=0; s<24; ++s) for (int u=0; u<4; ++u) for (int v=0; v<24; ++v)
        a[y][s][u][v][0] = d[y][s][u][v][b];
    for (int w=1; w<k; ++w) for (int y=0; y<4; ++y) for (int s=0; s<24; ++s)
    for (int u=0; u<4; ++u) for (int v=0; v<24; ++v) for (int i=0; i<4; ++i) for (int j=0; j<24; ++j)
        a[y][s][u][v][w] = min(a[y][s][u][v][w], a[y][s][i][j][w-1] + a[i][j][u][v][w-1]);
    if (k--) {
        for (; x2 && k>=0; --k) if ((1<<k) <= x2) {
            for (int y=0; y<4; ++y) for (int s=0; s<24; ++s) {
                long long &r = e[c^1][y][s] = 200000000000;
                for (int u=0; u<4; ++u) for (int v=0; v<24; ++v) r = min(r, e[c][u][v] + a[u][v][y][s][k]);
            }
            c ^= 1; x2 -= 1<<k;
        }
    }
    long long ans = e[c][y2][0];
    for (int i=1; i<24; ++i) ans = min(ans, e[c][y2][i]);
    return ans;
}

int main() {
    int t; cin >> t;
    for (int k=0; k<t; ++k) {
        if (k) cout << endl;
        cout << solve() << endl;
    }
    return 0;
}
相关推荐
Estella-Ealine2 天前
5.10 周赛vp 2026 ICPC Gran Premio de Mexico 1ra Fecha E题
icpc·2026
所以遗憾是什么呢?3 天前
【题解】Codeforces Round 1097 (Div. 2, Based on Zhili Cup 2026) (致理杯) ABCDEF
数据结构·算法·acm·codeforces·icpc·ccpc·xcpc
漂流瓶jz10 天前
UVA-1152 和为0的4个值 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·二分查找·题解·aoapc·算法竞赛入门经典·uva
AKDreamer_HeXY11 天前
QOJ 12255 - 36 Puzzle 题解
数据结构·c++·数学·算法·icpc·qoj
漂流瓶jz24 天前
UVA-120 煎饼 题解答案代码 算法竞赛入门经典第二版
数据结构·c++·算法·排序·aoapc·算法竞赛入门经典·uva
所以遗憾是什么呢?1 个月前
【题解】Codeforces Round 1081 (Div. 2)
数据结构·c++·算法·acm·icpc·ccpc·xcpc
漂流瓶jz1 个月前
UVA-10384 推门游戏 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·深度优先·题解·aoapc·算法竞赛入门经典·uva
漂流瓶jz1 个月前
UVA-11846 找座位 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·排序算法·深度优先·aoapc·算法竞赛入门经典·uva
漂流瓶jz3 个月前
UVA-12569 树上的机器人规划(简单版) 题解答案代码 算法竞赛入门经典第二版
算法·图论·dfs·bfs·uva·算法竞赛入门经典第二版·11214
超闻逸事3 个月前
题解:P13722 [GCPC 2024] Geometric Gridlock
icpc