URAL 1016. Cube on the Walk (分层图+最短路)

7 篇文章 2 订阅


 一个正方体,每个面标了一个数字,问,这个正方体,在8*8的棋盘上,从起点滚动到终点,所有朝下的面的数字之和的最小值(包括起点和终点)。

正方体,经过旋转,最多有24种状态。建立分层图,点数:24*8*8=1536.  稀疏图,用 SPFA 算法求最短路。

我直接写的一维数组。节点编号= 正方体的状态*64 +横坐标*8 +纵坐标 ;

开始求出所有24个状态(特殊情况可能少于24种状态)之间的状态转移。

然后SPFA求最短路。

using namespace std;
int dx[4]={-1, 1, 0, 0};
int dy[4]={ 0, 0, 1,-1};
int de[4]={ 5, 3, 1, 0};
struct Dice{
	int a[6];//按照题目给的顺序,分别为前,后,上,右,下,左 
	int next[4];//四个方向旋转后的编号
	void turn(int i){
		switch(i){
			case 0:left();break;
			case 1:right();break;
			case 2:up();break;
			case 3:down();break;
		}
	}
	void left(){int t=a[5];a[5]=a[2];a[2]=a[3];a[3]=a[4];a[4]=t;}//向左滚动
	void right(){int t=a[5];a[5]=a[4];a[4]=a[3];a[3]=a[2];a[2]=t;}//向右滚动
	void up(){int t=a[0];a[0]=a[4];a[4]=a[1];a[1]=a[2];a[2]=t;}//向上滚动
	void down(){int t=a[0];a[0]=a[2];a[2]=a[1];a[1]=a[4];a[4]=t;}//向下滚动
	bool operator ==(const Dice&B)const{
		int T=0;
		for(int i=0;i<6;i++) T+=a[i]==B.a[i];
		return T==6;
	}
	void show(){
		printf("\t(%d,%d,%d,%d,%d,%d)\n",a[0],a[1],a[2],a[3],a[4],a[5]);
	}
}D[24];int Dn;//记录24种状态
struct Node{
	int path;//记录最短路径
	int Dis;//记录最小值
	void init(int k){
		Dis=-1;path=k;
	}
}game[1536];
queue<int> Q;
bool inq[1536];
void Bfs(int k){
	int tempk=k;
	int index=tempk/64;tempk%=64;
	int x=tempk/8,y=tempk%8;
	for(int i=0;i<4;i++){//向4个方向扩展 
		int nx=x+dx[i],ny=y+dy[i];
		int Next=D[index].next[i]*64+nx*8+ny;//计算下个节点的编号 
		if(nx>=0&&nx<8&&ny>=0&&ny<8){//如果下一点在棋盘内 
			int Distance=game[k].Dis+D[index].a[de[i]];
			if(!~game[Next].Dis||Distance<game[Next].Dis){//如果未走过或者路径更短,更新 
				game[Next].Dis=Distance;
				game[Next].path=game[k].path;
				game[Next].path=k;
				if(!inq[Next]) Q.push(Next),inq[Next]=1;//若未入队,入队 
			}
		}
	}
}
void F(int i){//输出路径 
	if(i!=game[i].path) F(game[i].path);
	int t=i%64;
	printf(" %c%c",t/8+'a',t%8+'1');
}
int main(void)
{
	//处理输入 
	string a;int Sx,Sy,Dx,Dy;
	cin>>a;Sx=a[0]-'a';Sy=a[1]-'1';
	cin>>a;Dx=a[0]-'a';Dy=a[1]-'1';
	for(int i=0;i<6;i++) scanf("%d",&D[0].a[i]);
	//求出24状态之间的状态转移。
	Dn=1;
	for(int i=0;i<Dn;i++){//对于每个状态(开始只有一个状态) 
		for(int k=0;k<4;k++){// 向四个方向滚动 
			Dice temp=D[i];
			temp.turn(k);//记录滚动后的状态
			int Target=-1;
			for(int j=0;j<Dn;j++){//若出现过,记录编号
				if(D[j]==temp) {
					Target=j;break;
				}
			}
			if(!~Target){//若没出现过,用新的编号 
				Target=Dn++;
				D[Target]=temp;
			}
			D[i].next[k]=Target;//记录i往四个方向转动后的状态的编号 
		}
	}
	//显示Dices
	/* 
	for(int i=0;i<Dn;i++){
		printf("%d:",i);D[i].show();
		for(int k=0;k<4;k++) printf("->%d",D[i].next[k]);
		cout<<endl;
	}*/
	
	//计算  (SPFA)
	for(int i=0;i<1536;i++) game[i].init(i);
	memset(inq,0,sizeof(inq));
	Q.push(Sx*8+Sy);inq[Sx*8+Sy]=1;
	game[Sx*8+Sy].Dis=D[0].a[4];
	while(!Q.empty()){
		int cnt=Q.front();Q.pop();
		inq[cnt]=0;
		Bfs(cnt);
	}
	//搜索答案 
	int ANS=-1;int ANSI=-1;
	for(int i=0;i<Dn;i++){//搜索每一层
		if(~game[i*64+Dx*8+Dy].Dis){//如果可以到达
			if(!~ANS||game[i*64+Dx*8+Dy].Dis<ANS){//ANS未找到,或者新距离小于原始ANS  则更新。
				ANS=game[i*64+Dx*8+Dy].Dis;
				ANSI=i*64+Dx*8+Dy;
			}	
		}
	}
	//输出答案 
	cout<<ANS;
	F(ANSI);
	cout<<endl;
return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用代码解决这个问题The program committee of the school programming contests, which are often held at the Ural State University, is a big, joyful, and united team. In fact, they are so united that the time spent together at the university is not enough for them, so they often visit each other at their homes. In addition, they are quite athletic and like walking. Once the guardian of the traditions of the sports programming at the Ural State University decided that the members of the program committee spent too much time walking from home to home. They could have spent that time inventing and preparing new problems instead. To prove that, he wanted to calculate the average distance that the members of the program committee walked when they visited each other. The guardian took a map of Yekaterinburg, marked the houses of all the members of the program committee there, and wrote down their coordinates. However, there were so many coordinates that he wasn't able to solve that problem and asked for your help. The city of Yekaterinburg is a rectangle with the sides parallel to the coordinate axes. All the streets stretch from east to west or from north to south through the whole city, from one end to the other. The house of each member of the program committee is located strictly at the intersection of two orthogonal streets. It is known that all the members of the program committee walk only along the streets, because it is more pleasant to walk on sidewalks than on small courtyard paths. Of course, when walking from one house to another, they always choose the shortest way. All the members of the program committee visit each other equally often. Input The first line contains the number n of members of the program committee (2 ≤ n ≤ 105). The i-th of the following n lines contains space-separated coordinates xi, yi of the house of the i-th member of the program committee (1 ≤ xi, yi ≤ 106). All coordinates are integers. Output Output the average distance, rounded down to an integer, that a member of the program committee walks from his house to the house of his colleague.
05-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值