欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Problem 3 骰子游戏

程序员文章站 2022-07-07 10:40:52
...
背景
机房里面的人最爱玩游戏,这句活说的一点也不错,每天都会有人设计出一种新的小游戏。。。
问题描述Problem 3 骰子游戏
WZOI 的LZYP 大牛设计出一款小游戏。这个游戏地图是一个由N 行N 列的棋盘组成的(每一个小格都是1×1 正方形),如右图就是一个5×5 的的地图。LZYP 手中有一枚正方体,这枚正方体的棱长恰好为1。也就是说,这枚这正方体恰好可以覆盖一个棋盘格子。在正方体的每一个面上分别标上了一个非负整数W,当然正方体的六个面上的数字不一定相同。现在将这枚正方体放在棋盘上(恰好覆盖一个格子),一个人可以你在棋盘上滚动该立方体(立方体可以向其前、后、左、右四个方向滚动)。在滚动的过中,立方体底部与棋盘接触的那个面上的数字被加入总和S。LZYP 想要知道该怎样滚动这个正方体,才能使正方体从一个格子滚动到另一个格子得到的S 值最小。LZYP 想要知道这个最小值S,当然他会告诉你起始格子和目标格子的坐标。注意:立方体在起始格子和目标格子上的地面数字也要被计入总和,起始格子和目标格子是不同的。为了刁难你,LZYP 决定问你T 个问题,当然每次你都需要正确告诉他答案是多少;否则他就会一直烦着你,那么你就无法安心刷水题了。
输入格式
输入数据第一行包含三个整数N,T(分别用一个空格隔开),分别表示棋盘有N 行N 列,总共会有T 个问题;
第二行有6 个整数,表示立方体在开始格子上各个面上的6 个数字,顺序是:前面、后面、上面、右面、下面、左面。这6 个整数用空格隔开。
接下来 T行,每行四个整数 x1,y1,x2,y2,表示起始格子和目标格子的坐标(注意第一个是列号,第二个是行号)。输入数据保证会有一条路径从起始格子到达目标格子。
输出格式
输出数据总共T 行,每行一个整数S,表示从起始格子到目标格子的最小和。
样例输入输出 
Sample #1
cube.in 
5 1
0 8 1 2 1 1
5 2 5 3
cube.out
5
Sample #2
cube.in 
5 1
1 1 1 1 1 1
1 2 2 3
cube.out
3
样例解释
对于Sample #1,一条可行的路径就是(5,2)(4,2)(4,1)(5,1)(5,2)(5,3),底面的数字
分别为1,1,0,1,1,1。
对于Sample #2,一条可行的路径就是(1,2)(2,2)(2,3),底面的数字分别为1,1,1。
数据规模 
对于20%的数据,N≤10,0≤W≤10;
对于50%的数据,N≤50,0≤W≤100;
对于100%的数据,N≤100,0≤W≤1000。
对于100%的数据,T≤10.
时间限制
1s
提示
正方体的滚动是指,沿着底面与棋盘格子的一个公共边翻转。每个格子可以走多次,并且
每走一次,需要累加相应的权值。 

分析:
题目来源:改编自Ural 1016 Cube on the Walk
题目大意:给你一个N×N 的棋盘和一个立方体(每个面上有一个数字),将这个立方体从一个格子滚到另一个格子,要求输出最小的权值。
考察算法 拆点 广搜
算法一 
这是一道十分不错的广搜题目,它不同于一般的地图遍历。由于使用立方体的滚动来实现路径的形成,这就意味着每一个点会出现多种状态。同样这也就告诉我们这道题目需要拆点广搜。
我们不妨设这个立方体的前面、后面、上面、右面、下面、左面的标号分别为1,2,3,4,5,6。那么简单分析之后我们会发现只有以下24 种不同的状态:
123456,124563,125634,126345,213654,214365,215436,216543,
351624,352416,354162,356241,461325,462513,463251,465132,
531426,532614,534261,536142,641523,642315,643152,645231.
然后我们每一次滚动的时候做出相应的状态变化即可,具体实现可以参见程序,最后的答案就是min{dis[ex,ey,k] |k∈[1,24]}。
这道题目的难点就在于要想到拆点进行广搜,还需要有很强的实现能力。
时间复杂度:O(24*TN2) 空间复杂度:O(24*N2) 期望得分:100 分

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100+5;
const int size=262143,INF=2000000000;//262143是2^18-1(1<<18-1)。
int c[5][7]={{0,0,0,0,0,0},{0,1,2,6,3,4,5},{0,5,3,1,4,2,6},{0,1,2,4,5,6,3},{0,3,5,2,4,1,6}};
int state[25]={0,123456,124563,125634,126345,213654,214365,
215436,216543,351624,352416,354162,356241,
461325,462513,463251,465132,531426,532614,
534261,536142,641523,642315,643152,645231};
int dx[5]={0,1,0,-1,0},dy[5]={0,0,1,0,-1};
struct node{
    int x,y,k;
    int a[7];
};
int dis[maxn][maxn][25];
bool v[maxn][maxn][25];
node q[size];
int sx,sy,ex,ey,k;
int head,tail,n,ans,test;
int d[7],t[7];
int number()
{
    int i,x;
    x=0;
    for(i=1;i<=6;i++)
        x=x*10+t[i];
    for(i=1;i<=24;i++)
        if(x==state[i]) return i;
    return 0;
}
void bfs()
{
    int i,j;
    node now,tmp;
    head=0;
    tail=1;
    memset(dis,0x7f,sizeof(dis));
    q[1].x=sx;q[1].y=sy;q[1].k=0;
    for(i=1;i<=6;i++) q[1].a[i]=i;
    dis[sx][sy][0]=d[5];
    memset(v,0,sizeof(v));
    while(head<tail)
    {
        head=(head&size)+1;
        now=q[head];
        for(i=1;i<=4;i++)
        {
            tmp.x=now.x+dx[i];
            tmp.y=now.y+dy[i];
            if(tmp.x<1||tmp.x>n) continue;
            if(tmp.y<1||tmp.y>n) continue;
            for(j=1;j<=6;j++)
                t[j]=now.a[c[i][j]];
            k=number();
            if(dis[tmp.x][tmp.y][k]>dis[now.x][now.y][now.k]+d[t[5]])
            {
                dis[tmp.x][tmp.y][k]=dis[now.x][now.y][now.k]+d[t[5]];
                if(!v[tmp.x][tmp.y][k])
                {
                    v[tmp.x][tmp.y][k]=true;
                    tail=(tail&size)+1;
                    q[tail].x=tmp.x; q[tail].y=tmp.y; q[tail].k=k;
                    memcpy(q[tail].a,t,sizeof(t));
                }
            }
        }
        v[now.x][now.y][now.k]=false;
    }
    ans=INF;
    for(i=1;i<=24;i++)
        if(dis[ex][ey][i]<ans) ans=dis[ex][ey][i];
}
int main()
{
    int i;
    freopen("cube.in","r",stdin);
    freopen("cube.out","w",stdout);
    scanf("%d%d",&n,&test);
    for(int i=1;i<=6;i++)
    scanf("%d",&d[i]);
    for(i=1;i<=test;i++)
    {
        scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
        bfs();
        printf("%d\n",ans);
    }
    return 0;
}