记录编号 182872 评测结果 AAAAAAAAAA
题目名称 [CEPC 2003] 骰子游戏 最终得分 100
用户昵称 Gravatarmikumikumi 是否通过 通过
代码语言 C++ 运行时间 0.880 s
提交时间 2015-08-29 10:37:38 内存使用 2.01 MiB
显示代码纯文本
#include<cstdio>
#include<deque>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const LL maxn=LL(1e17);
const int SIZEH=4,SIZENUM=6;
const int SIZEC=20;
int L[7];
int x1,x2;
int y3,y2;
LL f[3000];
int opposite[7]={0};//第i面的对面是什么
int id[5][SIZENUM+1][SIZENUM+1]={0};//状态编号,分别是行,正面,上面
int N;//总状态数
int C;//c的状态数
int S;//起始状态
int onleft[40][40]={0};
deque<pair<int,int> > c[3000];
pair<int,pair<int,int> > state[720];
deque<int> T;
void check_u(int u)
{
	int tem=u%N;
	if(u==0) u=N;
	cout<<(u-1)/N<<" ";
	cout<<state[tem].first<<" "<<state[tem].second.first<<" "<<state[tem].second.second<<endl;;
}
class miku
{
public:
	int n,m;
	LL s[160][160];
	miku()
	{
		n=m=0;
		for(int i=0;i<=144;i++)
			for(int j=0;j<=144;j++)
				s[i][j]=maxn;
	}
	void print()
	{
		cout<<n<<" "<<m<<endl;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				cout<<s[i][j]<<" ";//check_u(j);
			}
			cout<<endl;
		}
		cout<<endl;
	}
	void make(int a)
	{
		n=m=a;
		for(int i=1;i<=n;i++)
			s[i][i]=0;
	}
};
inline miku operator * (miku a,miku b)
{
	miku c;
	c.n=a.n;c.m=b.m;
	for(int i=1;i<=c.n;i++)
		for(int j=1;j<=c.m;j++)
		{
			for(int k=1;k<=a.m;k++)
			c.s[i][j]=min(c.s[i][j],a.s[i][k]+b.s[k][j]);
		}
	return c;
}
inline miku quickpow(miku a,LL b)
{
	miku re;
	re.make(a.n);
	//re.print();
	//cout<<b<<endl;
	while(b)
	{
		if(b&1) re=re*a;
		b>>=1;a=a*a;
	}
	//re.print();
	return re;
}
void check_c()
{
	for(int u=1;u<=C;u++)
	{
		check_u(u);
		cout<<"to:"<<endl;
		for(int i=0;i<c[u].size();i++)
		{
			check_u(c[u][i].first);
			cout<<c[u][i].second<<endl;
		}
		cout<<endl;
	}
}
void check_f()
{
	check_u(S);
	for(int i=1;i<=N;i++) {check_u(i+8*N);cout<<" "<<f[i+8*N]<<endl;}
}
int left(int j,int k)
{
	return onleft[j][k];
}
int right(int j,int k)
{
	return opposite[onleft[j][k]];
}
void make_c()
{
	C=SIZEC*N;
	for(int x=0;x<SIZEC;x++)
		for(int y=1;y<=4;y++)
		    for(int fr=1;fr<=6;fr++)//枚举正面
				for(int up=1;up<=6;up++)
			    {
					if(fr==up||fr==opposite[up]) continue;
					int u=id[y][fr][up]+x*N;;
				    if(x>0) c[u].push_back(make_pair(id[y][fr][right(fr,up)]+(x-1)*N,L[right(fr,up)]));
					if(x<SIZEC-1) c[u].push_back(make_pair(id[y][fr][left(fr,up)]+(x+1)*N,L[left(fr,up)]));
					if(y>1) c[u].push_back(make_pair(id[y-1][up][opposite[fr]]+x*N,L[opposite[fr]]));
					if(y<4) c[u].push_back(make_pair(id[y+1][opposite[up]][fr]+x*N,L[fr]));
			    }
	//check_c();
}
void prepare()
{
	opposite[1]=6;opposite[6]=1;
	opposite[2]=5;opposite[5]=2;
	opposite[4]=3;opposite[3]=4;
	if(x1>x2)//镜像反转
	{
		swap(L[2],L[5]);
		swap(L[3],L[4]);
		swap(x1,x2);
		y3=4+1-y3;y2=4+1-y2;
	}
	if(x1!=0) x2-=x1;x1=0;
	N=0;
	for(int i=1;i<=4;i++)
		for(int j=1;j<=6;j++)
			for(int k=1;k<=6;k++)
			{
				if(j==k||j==opposite[k]) continue;
				id[i][j][k]=++N;
				state[N]=make_pair(i,make_pair(j,k));
			}
	S=id[y3][2][1];
	onleft[1][2]=4;onleft[1][3]=2;
	onleft[2][1]=3;onleft[2][3]=6;
	onleft[3][1]=5;onleft[3][2]=1;
	for(int i=1;i<=6;i++)
		for(int j=1;j<=6;j++)
		{
			if(i==j||i==opposite[j]) continue;
			if(onleft[i][j]) continue;
			else if(onleft[i][opposite[j]]) onleft[i][j]=opposite[onleft[i][opposite[j]]];
			else if(onleft[opposite[i]][j]) onleft[i][j]=opposite[onleft[opposite[i]][j]];
			else if(onleft[opposite[i]][opposite[j]]) onleft[i][j]=onleft[opposite[i]][opposite[j]];
		}
	make_c();
	for(int i=1;i<=6;i++)
		for(int j=1;j<=6;j++)
		{
			if(i==j||i==opposite[j]) continue;
			T.push_back(id[y2][i][j]);
		}
}
void spfa(int s,int n)
{
	bool inq[3000]={0};
	deque<int> Q;
	for(int i=1;i<=n;i++) f[i]=maxn;
	inq[s]=1;f[s]=0;Q.push_back(s);
	//check_c();
	while(!Q.empty())
	{
		int x=Q.front();Q.pop_front();inq[x]=0;
		for(int i=0;i<c[x].size();i++)
		{
			pair<int,int> v=c[x][i];
			if(f[x]+v.second<f[v.first])
			{
				f[v.first]=f[x]+v.second;
				if(!inq[v.first])
				{
					Q.push_back(v.first);
					inq[v.first]=1;
				}
			}
		}
	}
}
void get(miku &I,miku &D)
{
	I.n=1;I.m=N;
	int tem=SIZEC/2-1;
	//cout<<N<<endl;
	spfa(S+tem*N,C);
	D.m=D.n=N;
	//for(int i=1;i<=C;i++) cout<<f[i]<<endl;
	for(int i=1;i<=N;i++) I.s[1][i]=f[i+tem*N];
	for(int i=1;i<=N;i++)
	{
		spfa(i,C);
		for(int j=1;j<=N;j++)
			D.s[i][j]=f[j+N];
	}
}
void work()
{
	miku I,D;
	get(I,D);
	//D.print();
	I=I*quickpow(D,x2-x1);
	LL ans=maxn;
	for(int i=0;i<T.size();i++)
	{
		ans=min(I.s[1][T[i]],ans);
	}
	cout<<ans;
}
int main()
{
	freopen("dicecontest.in","r",stdin);
	freopen("dicecontest.out","w",stdout);
	for(int i=1;i<=6;i++)
		scanf("%d",&L[i]);
	scanf("%d%d%d%d",&x1,&y3,&x2,&y2);//lld
	prepare();
	//cout<<1<<endl;
	work();
	return 0;
}