ZOJ 1103 Hike on a Graph(BFS)

11 篇文章 0 订阅

题意:给出一个完全图,任意两点间都有边,每条边都有一个颜色,在某3个点上各放了1个棋子,每次只允许让一个棋子通过一条边走到另一个点上并且走的这条边的颜色必须和另外两个棋子之间的边颜色相同(完全图,任意两点都有边),求走到同一个点上最少步数.

思路:可以设计一个3维的状态,dis[x][y][z]代表3个点分别在x, y, z点上时候的最少步数,那么就可以用类似spfa的松弛方法来更新就可以了.

注意刚开始3个点可能已经在同一个点上了.

#include <cstdio>
#include <queue>
#include <memory.h>
using namespace std;
const int MAX = 51;

int dis[MAX][MAX][MAX];
int g[MAX][MAX];
int n;
int s1, s2, s3;
struct Node{
	int x, y, z, step;
	Node(int x_ = 0, int y_ = 0, int z_ = 0, int step_ = 0):x(x_), y(y_), z(z_), step(step_){}
};
int spfa(){
	memset(dis, 0x20, sizeof(dis));
	dis[s1][s2][s3] = 0;
	int ans = 0x20202020;
	queue<Node> q;
	q.push(Node(s1, s2, s3, 0));

	while(!q.empty()){
		Node f = q.front();
		q.pop();
		int x = f.x, y = f.y, z = f.z;
		for(int i = 1; i <= n; ++i){
			if(i != x && g[x][i] == g[y][z]){
				if(dis[i][y][z] > f.step + 1){
					dis[i][y][z] = f.step + 1;
					q.push(Node(i, y, z, f.step + 1));
				}
			}
		}
		for(int i = 1; i <= n; ++i){
			if(i != y && g[y][i] == g[x][z]){
				if(dis[x][i][z] > f.step + 1){
					dis[x][i][z] = f.step + 1;
					q.push(Node(x, i, z, f.step + 1));
				}
			}
		}
		for(int i = 1; i <= n; ++i){
			if(i != z && g[z][i] == g[x][y]){
				if(dis[x][y][i] > f.step + 1){
					dis[x][y][i] = f.step + 1;
					q.push(Node(x, y, i, f.step + 1));
				}
			}
		}
	}
	for(int i = 1; i <= n; ++i){
		if(dis[i][i][i] < ans){
			ans = dis[i][i][i];
		}
	}
	return ans;
}
int main(int argc, char const *argv[]){
	while(scanf("%d", &n) == 1){
		if(!n)break;
		scanf("%d%d%d", &s1, &s2, &s3);
		for(int i = 1; i <= n; ++i){
			for(int j = 1; j <= n; ++j){
				char c[2];
				scanf("%s", c);
				g[i][j] = c[0];
			}
		}
		if(s1 == s2 && s1 == s3){
			printf("0\n");
			continue;
		}
		int ans = spfa();
		if(ans == 0x20202020){
			printf("impossible\n");
		}else{
			printf("%d\n", ans);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值