【JZOJ4628】立方体
Description
Solution
首先注意数字行是从下到上的。
一个显然的结论是,我们如果确定了色子两个相邻面的位置,那么整个色子的状态就确定了。
于是我们很粗暴地手打一个表,打出每个状态往前往后往左往右的状态(这个有规律)。
然后我们设 Fi,j,k,l 表示当前坐标为 (i,j) ,状态为 (k,l) 的最小的总和。
于是在spfa中转移(其中 (i′,j′) 表示新坐标, (k′,l′) 表示新状态, p 表示朝下的那一面的编号):
Fi′,j′,k′,l′=min(Fi,j,k,l+ap)
只要有毅力就能AC!
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 9
#define M 100001
using namespace std;
char s1[4],s2[4];
int a[7];
int d[M][3];
int dl[M][3];
int fx[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int f[N][N][7][7];
bool bz[N][N][7][7];
int zh[201];
int db[4][7][7][2]=
{
{
{0},
{{0},{0},{0},{4,3},{5,4},{6,5},{3,6}},
{{0},{0},{0},{6,3},{3,4},{4,5},{5,6}},
{{0},{6,1},{4,2},{0},{1,4},{0},{2,6}},
{{0},{3,1},{5,2},{2,3},{0},{1,5},{0}},
{{0},{4,1},{6,2},{0},{2,4},{0},{1,6}},
{{0},{5,1},{3,2},{1,3},{0},{2,5},{0}}
},
{
{0},
{{0},{0},{0},{6,3},{3,4},{4,5},{5,6}},
{{0},{0},{0},{4,3},{5,4},{6,5},{3,6}},
{{0},{4,1},{6,2},{0},{2,4},{0},{1,6}},
{{0},{5,1},{3,2},{1,3},{0},{2,5},{0}},
{{0},{6,1},{4,2},{0},{1,4},{0},{2,6}},
{{0},{3,1},{5,2},{2,3},{0},{1,5},{0}}
},
{
{0},
{{0},{0},{0},{3,2},{4,2},{5,2},{6,2}},
{{0},{0},{0},{3,1},{4,1},{5,1},{6,1}},
{{0},{1,5},{2,5},{0},{4,5},{0},{6,5}},
{{0},{1,6},{2,6},{3,6},{0},{5,6},{0}},
{{0},{1,3},{2,3},{0},{4,3},{0},{6,3}},
{{0},{1,4},{2,4},{3,4},{0},{5,4},{0}}
},
{
{0},
{{0},{0},{0},{5,1},{6,1},{3,1},{4,1}},
{{0},{0},{0},{5,2},{6,2},{3,2},{4,2}},
{{0},{2,3},{1,3},{0},{6,3},{0},{4,3}},
{{0},{2,4},{1,4},{5,4},{0},{3,4},{0}},
{{0},{2,5},{1,5},{0},{6,5},{0},{4,5}},
{{0},{2,6},{1,6},{5,6},{0},{3,6},{0}}
},
};
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
for(char i='a';i<='h';i++)
zh[i]=i-'a'+1;
int n;
cin>>s1>>s2;
int qdx=s1[1]-48,qdy=zh[s1[0]],zdx=s2[1]-48,zdy=zh[s2[0]];
fo(i,1,6) scanf("%d",&a[i]);
qdx=9-qdx;
zdx=9-zdx;
int l=0,r=1;
memset(f,60,sizeof(f));
d[1][1]=qdx;
d[1][2]=qdy;
dl[1][1]=5;
dl[1][2]=1;
f[qdx][qdy][5][1]=0;
bz[qdx][qdy][5][1]=true;
int ans=2147483647;
while(l<r)
{
l++;
int x=d[l][1],y=d[l][2];
int p=dl[l][1],q=dl[l][2];
fo(i,0,3)
{
int xx=x+fx[i][0],yy=y+fx[i][1];
if(xx<1 || xx>8 || yy<1 || yy>8) continue;
int pp=db[i][p][q][0],qq=db[i][p][q][1];
if(f[xx][yy][pp][qq]>f[x][y][p][q]+a[pp])
{
f[xx][yy][pp][qq]=f[x][y][p][q]+a[pp];
if(xx==zdx && yy==zdy)
{
ans=min(ans,f[xx][yy][pp][qq]+a[5]);
continue;
}
if(!bz[xx][yy][pp][qq])
{
r++;
d[r][1]=xx;
d[r][2]=yy;
dl[r][1]=pp;
dl[r][2]=qq;
}
}
}
bz[x][y][p][q]=false;
}
cout<<ans;
}