【BZOJ2464】【中山市选2009】小明的游戏 最短路水过

题解:最短路pqspfa200ms,一眼题,

另一种想出来没写的做法:二分答案,上界n+m

时间复杂度O(n*m*log(n+m)),二分+深搜看能不能找到t

最短路代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 505
#define NN 251000
#define inf 0x3f3f3f3f
using namespace std;
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
struct KSD
{
	int v,len,next;
}e[NN<<2];
int head[NN],cnt;
void add(int u,int v,int len)
{
	++cnt;
	e[cnt].v=v;
	e[cnt].len=len;
	e[cnt].next=head[u];
	head[u]=cnt;
}
int dist[NN],in[NN];
struct Vayne
{
	int f,v;
	bool operator < (const Vayne &a)const
	{return f>a.f;}
	Vayne(){}
	Vayne(int _f,int _v):f(_f),v(_v){}
};
int s,t,n,m,id[N][N],num;
char map[N][N];
priority_queue<Vayne>q;
void init()
{
	num=cnt=0;
	memset(head,0,sizeof(head));
}
int spfa()
{
	while(!q.empty())q.pop();
	memset(dist,0x3f,sizeof(dist));
	memset(in,0,sizeof(in));
	int i,u,v,temp;
	dist[s]=0;
	in[s]=1;
	q.push(Vayne(0,s));
	while(!q.empty())
	{
		Vayne U=q.top();q.pop();
		u=U.v;
		in[u]=0;
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].v;
			if(dist[v]>dist[u]+e[i].len)
			{
				dist[v]=dist[u]+e[i].len;
				if(!in[v])
				{
					in[v]=1;
					q.push(Vayne(dist[v],v));
				}
			}
		}
	}
	return dist[t];
}
bool build()
{
	int i,j,k;
	int a,b,c;
	int x,y;
	init();
	scanf("%d%d",&n,&m);
	if(n==0&&m==0)return 0;
	for(i=1;i<=n;i++)scanf("%s",map[i]+1);
	for(i=1;i<=n;i++)for(j=1;j<=m;j++)id[i][j]=++num;
	for(i=1;i<=n;i++)for(j=1;j<=m;j++)
	{
		int iid=id[i][j];
		for(k=0;k<4;k++)
		{
			x=i+dx[k];
			y=j+dy[k];
			if(id[x][y])
			{
				int len=(map[i][j]==map[x][y]);
				add(iid,id[x][y],!len);
				add(id[x][y],iid,!len);
			}
		}
	}
	scanf("%d%d%d%d",&a,&b,&x,&y);
	s=id[a+1][b+1];
	t=id[x+1][y+1];
	return 1;
}
int main()
{
//	freopen("test.in","r",stdin);
	while(build())printf("%d\n",spfa());
	return 0;
}
时间: 2024-10-13 20:49:56

【BZOJ2464】【中山市选2009】小明的游戏 最短路水过的相关文章

bzoj2464: 中山市选[2009]小明的游戏(最短路)

2464: 中山市选[2009]小明的游戏 题目:传送门 题解: 最短路的裸题... 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int dx[5]={0,1,-1,0,0}; 8 int dy[5]={0,0,0,-1,1}; 9 st

BZOJ2464: 中山市选[2009]小明的游戏

2464: 中山市选[2009]小明的游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 280  Solved: 124[Submit][Status] Description 小 明最近喜欢玩一个游戏.给定一个n * m的棋盘,上面有两种格子#和@.游戏的规则很简单:给定一个起始位置和一个目标位置,小明每一步能向上,下,左,右四个方向移动一格.如果移动到同一类 型的格子,则费用是0,否则费用是1.请编程计算从起始位置移动到目标位置的最小花费.

BZOJ 2464 中山市选 2009 小明的游戏 最短路

题目大意:给出一个地图,如果经过两个不同的区块,需要花费1,否则不需要花费.问从st到ed最小需要花费多少. 思路:签到题. #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 510 #define MAXP 250010 #define MAXE 2000010 using name

2463: [中山市选2009]谁能赢呢?

2463: [中山市选2009]谁能赢呢? Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 830  Solved: 586[Submit][Status] Description 小明和小红经常玩一个博弈游戏.给定一个n×n的棋盘,一个石头被放在棋盘的左上角.他们轮流移动石头.每一回合,选手只能把石头向上,下,左,右四个方向移动一格,并且要求移动到的格子之前不能被访问过.谁不能移动石头了就算输.假如小明先移动石头,而且两个选手都以最优策略走步,问

bzoj2463: [中山市选2009]谁能赢呢?

奇偶即可判断输赢 #include<cstdio> #include<cctype> int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } int main(){ int n; while(n=read()) { n%2?printf("Bob\n"):printf(

bzoj千题计划169:bzoj2463: [中山市选2009]谁能赢呢?

http://www.lydsy.com/JudgeOnline/problem.php?id=2463 n为偶数时,一定可以被若干个1*2 矩形覆盖 先手每次从矩形的一端走向另一端,后手每次走向一个新的矩形 所以先手必胜 n为奇数时,先手走完一步后,剩下同n为偶数 所以先手必败 #include<cstdio> using namespace std; int main() { int n; while(scanf("%d",&n)!=EOF) { if(!n)

BZOJ 2466: [中山市选2009]树( 高斯消元 )

高斯消元解异或方程组...然后对自由元进行暴搜.树形dp应该也是可以的... -------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<bitset> using namespace std; const int ma

bzoj2466: [中山市选2009]树

同上一题.(应该可以树形dp,然而我不会... #include<cstdio> #include<cstring> #include<iostream> #include<bitset> #include<algorithm> using namespace std; #define REP(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #

【BZOJ2466】[中山市选2009]树 树形DP

[BZOJ2466][中山市选2009]树 Description 图论中的树为一个无环的无向图.给定一棵树,每个节点有一盏指示灯和一个按钮.如果节点的按扭被按了,那么该节点的灯会从熄灭变为点亮(当按之前是熄灭的),或者从点亮到熄灭(当按之前是点亮的).并且该节点的直接邻居也发生同样的变化. 开始的时候,所有的指示灯都是熄灭的.请编程计算最少要按多少次按钮,才能让所有节点的指示灯变为点亮状态. Input 输入文件有多组数据. 输入第一行包含一个整数n,表示树的节点数目.每个节点的编号从1到n.