UVALive 6665 Dragon’s Cruller (BFS + 优先队列+hash)

题目链接:传送门

题意:

一个九宫格,给定你初始状态和结束状态,每次横向移动和纵向移动都有一定的花费,

问从初始状态到结束状态的最小花费。

分析:

BFS,用优先队列维护到达当前状态的最优值,用hash判断当前的状态是否达到过。

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

const int INF = 1e9+7777;

int fac[9]= {1,1,2,6,24,120,720,5040,40320}; //康托展开,用来hash

struct nod {
    int mp[9],pos,cost;
    bool operator <(const struct nod &tmp)const {
        return this->cost > tmp.cost;
    }
} P;

int dx[4]= {1,-1,0,0};
int dy[4]= {0,0,-1,1};
int s[9],e[9];
int cv,ch;
int vis[40320*9+100];

int getHashVal(int *a) { //hash得到hash值。
    int val = 0;
    for(int i=0; i<9; i++) {
        int cnt=0;
        for(int j=0; j<i; j++) cnt+=(a[j]>a[i]);
        val+=cnt*fac[i];
    }
    return val;
}

bool check(nod tmp) {
    int cnt = 0;
    for(int i=0; i<9; i++)
        cnt+=(tmp.mp[i]==e[i]);
    return cnt==9;
}

int BFS(nod st) {
    priority_queue<nod> Q;
    Q.push(st);
    vis[getHashVal(st.mp)]=0;
    while(!Q.empty()) {
        nod top = Q.top();
        Q.pop();
        if(check(top)) {
            return top.cost;
        }
        for(int i=0; i<4; i++) {
            int tmppos = top.pos;
            int nowx = (top.pos/3+dx[i]+3)%3;//转换
            int nowy = top.pos%3+dy[i];
            if(nowy==3){
                nowy=0;
                nowx=(nowx+1)%3;
            }
            if(nowy==-1){
                nowy=2;
                nowx=(nowx-1+3)%3;
            }
            swap(top.mp[nowx*3+nowy],top.mp[tmppos]);
            if(i<2) top.cost+=cv;
            else top.cost+=ch;
            top.pos=nowx*3+nowy;
            int val = getHashVal(top.mp);
            if(top.cost<vis[val]) {
                Q.push(top);
                vis[val]=top.cost;
            }
            swap(top.mp[nowx*3+nowy],top.mp[tmppos]);
            if(i<2) top.cost-=cv;
            else top.cost-=ch;
            top.pos=tmppos;
        }
    }
}

nod init() {
    nod st;
    for(int i=0; i<40320*9+100; i++) vis[i]=INF;
    for(int i=0; i<9; i++) {
        st.mp[i]=s[i];
        if(s[i]==0) st.pos=i;
    }
    st.cost=0;
    return st;
}

int main() {
    while(~scanf("%d%d",&ch,&cv)) {
        if(cv==0&&ch==0) break;
        for(int i=0; i<9; i++) scanf("%d",s+i);
        for(int i=0; i<9; i++) scanf("%d",e+i);
        printf("%d\n",BFS(init()));
    }
    return 0;
}

/*
4 9
6 3 0
8 1 2
4 5 7
6 3 0
8 1 2
4 5 7
31 31
4 3 6
0 1 5
8 2 7
0 3 6
4 1 5
8 2 7
92 4
1 5 3
4 0 7
8 2 6
1 5 0
4 7 3
8 2 6
12 28
3 4 5
0 2 6
7 1 8
5 7 1
8 6 2
0 3 4

0
31
96
312
*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 06:59:55

UVALive 6665 Dragon’s Cruller (BFS + 优先队列+hash)的相关文章

UVALive 6665 Dragon&#226;??s Cruller --BFS,类八数码问题

题意大概就是八数码问题,只不过把空格的移动方式改变了:空格能够向前或向后移动一格或三格(循环的). 分析:其实跟八数码问题差不多,用康托展开记录状态,bfs即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue&g

UVALive 6485 Electric Car Rally (BFS,优先队列)

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4496 In an attempt to demonstrate the practicality of electric cars, ElecCarCo is sponsoring a cross-country road rally. There are n chargin

UVALive 6665 Dragonas Cruller

题目链接:https://icpcarchive.ecs.baylor.edu/external/66/6665.pdf 题目大意: 有一个3 * 3 的格子: 每个格子上面的数字能够朝上下左右四个方向移动.假设移出范围.则到与其边界上字母相应的还有一边. 例如以下图所看到的: 空白部分分别向上下左右移动之后的情况. 如今.给你左右移动的费用ch,上下移动cv.给你一个初始状态(9个数字,当中0代表该空格为空),一个结束状态,问从初始状态移动到结束状态的最小花费. 解题思路: 事实上这道题想法非

[ACM] hdu 1242 Rescue (BFS+优先队列)

Rescue Problem Description Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison. Angel's friends want to save Angel. Their task is:

Battle City BFS+优先队列

Battle City Many of us had played the game "Battle city" in our childhood, and some people (like me) even often play it on computer now. What we are discussing is a simple edition of this game. Given a map that consists of empty spaces, rivers,

hdu 1242 Rescue(bfs+优先队列)

Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison. Angel's friends want to save Angel. Their task is: approach Angel. We assume

hdu 1242 Rescue (BFS+优先队列)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1242 这道题目我是用BFS+优先队列做的.听说只用bfs会超时. 因为这道题有多个营救者,所以我们从被营救者开始bfs,找到最近的营救者就是最短时间. 先定义一个结构体,存放坐标x和y,还有到达当前点(x,y)消耗的时间. struct node { int x,y; int time; friend bool operator < (const node &a,const node &

hdu 2102 A计划 详细题解 (BFS+优先队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 这道题属于BFS+优先队列 开始看到四分之一的AC率感觉有点吓人,后来一做感觉就是模板改了点东西而已,一遍就AC了,不过在主函数和全局变量里面都定义了n和m导致我白白浪费了debug的时间.果然全局变量得小心用啊. 跟模板一样的,定义一个结构体,只不过多加了个参数,就是迷宫的层数,我用0代表第一层,1代表第二层,这在数组里面会体现的. struct node { int index;//层数

hdu 3345 War Chess (bfs+优先队列)

War Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1732    Accepted Submission(s): 416 Problem Description War chess is hh's favorite game: In this game, there is an N * M battle map, an