UVALive 6665 Dragonas Cruller[通俗易懂]

UVALive 6665 Dragonas Cruller

大家好,又见面了,我是全栈君。

题目链接:https://icpcarchive.ecs.baylor.edu/external/66/6665.pdf

题目大意:

有一个3 * 3 的格子:

UVALive 6665 Dragonas Cruller[通俗易懂]

UVALive 6665 Dragonas Cruller[通俗易懂]

每个格子上面的数字能够朝上下左右四个方向移动。假设移出范围。则到与其边界上字母相应的还有一边。

例如以下图所看到的:

UVALive 6665 Dragonas Cruller[通俗易懂]

UVALive 6665 Dragonas Cruller[通俗易懂]

空白部分分别向上下左右移动之后的情况。

如今。给你左右移动的费用ch,上下移动cv。给你一个初始状态(9个数字,当中0代表该空格为空),一个结束状态,问从初始状态移动到结束状态的最小花费。

解题思路:

事实上这道题想法非常easy,简单的bfs + 优先队列。主要是细节处理方面比較麻烦。

把上述九宫格变为一个序列,会发现状态最多就9!种,所以状态能够依照序列的排序离散化。详细參考代码。

然后改成序列之后,会发现左右移动事实上就是 i + 1。 i – 1的操作。上下移动是 i + 3, i – 3 的操作。

代码:

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<fstream>
#include<cstring>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#define maxn 1000
#define INF (1<<30)
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))
#define For(i, n) for (int i = 0; i < n; i++)
#define debug puts("===============")
const int N = 362881;
typedef long long ll;
using namespace std;
int ch, cv;
int fac[10];
struct node {
    int x, w;
    node(int _x, int _w) {
        x = _x, w = _w;
    }
    bool operator < (const node & T) const {
        return w > T.w;
    }
};
void Atoint(int* a, int &x) {
    int i, j, y;
    x = 0;
    for (i = 0; i < 9; i++) {
        y = a[i];
        for (j = 0; j < i; j++)
            if (a[j] < a[i]) y--;
        x += fac[8 - i] * y;
    }
}
void inttoA(int x, int* a) {
    int has[10] = {0};
    int i, j, y;
    for (i = 0; i < 9; i++) {
        y = x / fac[8 - i];
        for (j = 0; j < 9; j++) if (!has[j]) {
            if (y == 0) break;
            y--;
        }
        a[i] = j, has[j] = 1, x %= fac[8 - i];
    }
}
int st, ed;
priority_queue<node> q;
int d[N], vis[N], a[10], b[10];
void update(int x, int w) {
    if (!vis[x] && d[x] > w) {
        d[x] = w, q.push(node(x, w));
    }
}
void work() {
    Atoint(a, st), Atoint(b, ed);
    while(!q.empty()) q.pop();
    memset(d, 0x7F, sizeof(d));
    memset(vis, 0, sizeof(vis));
    d[st] = 0;
    q.push(node(st, 0));
    int x, w, i, y;
    while(!q.empty()) {
        x = q.top().x, w = q.top().w, q.pop();
        if (vis[x]) continue;
        vis[x] = 1;
        if (x == ed) {
            printf("%d\n", w);
            break;
        }
        inttoA(x, a);
        for (i = 0; i < 9; i++) if (!a[i]) break;
        swap(a[i], a[(i + 1) % 9]);
        Atoint(a, y);
        update(y, w + ch);
        swap(a[i], a[(i + 1) % 9]);
        swap(a[i], a[(i + 8) % 9]);
        Atoint(a, y);
        update(y, w + ch);
        swap(a[i], a[(i + 8) % 9]);
        swap(a[i], a[(i + 3) % 9]);
        Atoint(a, y);
        update(y, w + cv);
        swap(a[i], a[(i + 3) % 9]);
        swap(a[i], a[(i + 6) % 9]);
        Atoint(a, y);
        update(y, w + cv);
    }
}
int main () {
    //freopen("1.txt", "r", stdin);
    fac[0] = 1;
    for (int i = 1; i < 10; i++) fac[i] = fac[i - 1] * i;
    while(scanf("%d%d", &ch, &cv), ch || cv) {
        for (int i = 0; i < 9; i++) scanf("%d", a + i);
        for (int i = 0; i < 9; i++) scanf("%d", b + i);
        work();
    }
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115862.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 基于speech模块的久坐提醒小程序「建议收藏」

    基于speech模块的久坐提醒小程序「建议收藏」每天在电脑前坐很长的时间,因为有时候太过投入一下子就过去了若干个小时,容易猝死。于是心血来潮的想要写一个防久坐提醒小程序:第一种模式(最简单模式),若输入伏案工作时间数值不对则产生一个错误并退出。代码如下:importspeechimporttimeclassDebug:def__init__(self):self.start_time=time.time()self.minutes=int(input(“How

    2022年9月30日
    0
  • 比较列存储索引与行索引

    比较列存储索引与行索引

    2021年11月24日
    44
  • java的二维数组讲解_javalambda表达式语法

    java的二维数组讲解_javalambda表达式语法1、二维数组概述1、二维数组其实就是一个特殊的一维数组,一维数组中每个元素就是一个一维数组2、三维数组又是一个特殊的二维数组2、二维数组的定义int[][]a=newint[10][10];String[][]b=newString[10][10];3、初始化二维数组//静态初始化int[][]a={{1,2,3,4},{4,5,6,7},{8,9,10,11}};//动态初始化

    2022年10月25日
    0
  • linux卸载eclipse,ubuntu卸载eclipse[通俗易懂]

    linux卸载eclipse,ubuntu卸载eclipse[通俗易懂]1.安装JDK6先确认已经添加了软件源,在系统-系统管理-软件源-其它软件,确保已经选中http://archive.canonical.com/ubuntulucidpartner这个源。sudoapt-getinstallsun-java6-jdk设置系统环境变量exportJAVA_HOME=/usr/lib/jvm/java-6-sun(根据具体的安装路径)expor…

    2022年5月29日
    55
  • 中缀表达式转换为后缀表达式(栈的使用)

    中缀表达式如1*2+(2-1), 其运算符一般出现在操作数之间, 因此称为中缀表达式,也就是大家编程中写的表达式。编译系统不考虑表达式的优先级别, 只是对表达式从左到右进行扫描, 当遇到运算符时, 就把其前面的两个操作数取出, 进行操作。为达到上述目的, 就要将中缀表达式进行改写,变为后缀表达式 如上面的表达式1*2+(2-1), 就变为12*21-+;后缀表达式中不含有括号, 且

    2022年3月9日
    51
  • APK签名流程详解

    APK签名流程详解本文最好对照我的APK签名解析示例进行阅读.示例中的关键文件说明:keys-存放签名公私钥的目录signed_logcat.apk-已经使用keys目录中的密钥签名后的apksigned_logcat-signed_logcat.apk解压出来的内容sign.cmd-对apk签名的批处理命令signapk.jar-java版本的apk签名工具

    2022年5月11日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号