{POJ}{3897}{Maze Stretching}{二分答案+BFS}

题意:给定迷宫,可以更改高度比,问如何使最短路等于输入数据。

思路:由于是单调的,可以用二分答案,然后BFS验证。这里用优先队列,每次压入也要进行检查(dis大小)防止数据过多,A*也可以。好久不写图论,WA成狗

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <memory>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
#include <stack>
using namespace std;

#define CLR(x,y) memset(x,y,sizeof(x))
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
#define rep(i,x,y) for(i=x;i<y;++i)

#define SET_NODE(no,a,b,c) {no.x=a;no.y=b;no.val=c;}

const int MAXN = 200;
const double INF = 1<<30;
const double EPS = 0.000001;

int dir[4][2]={1,0,-1,0,0,1,0,-1};
int n,m;
int tag[MAXN];
char g[MAXN][MAXN];
double dist;
bool visit[MAXN][MAXN];
double dis[MAXN][MAXN];
typedef struct
{
	int x,y;
	double val;
}Node;
Node s,e,node;
bool operator < (const Node& a,const Node& b)
{
    return a.val > b.val;
}
bool check(const int& x, const int& y)
{
	if(x<0||x>=n) return false;
	if(y<0||y>=m) return false;
	if(g[x][y] == ‘#‘) return false;
	if(visit[x][y]) return false;
	return true;
}

double BFS(double len)
{
	int i,j,k;
	Node tmp;

	priority_queue<Node> q;

	q.push(s);

	CLR(visit,0);

	rep(i,0,n)
		rep(j,0,m)
			dis[i][j] = INF;

	while(!q.empty())
	{
		node = q.top();
		q.pop();
		visit[node.x][node.y] = true;

		if(node.x == e.x && node.y == e.y)
			return node.val;

		if(check(node.x+1,node.y)){
			SET_NODE(tmp,node.x+1,node.y,node.val+len);
			if(tmp.val<dis[tmp.x][tmp.y])
			{
				dis[tmp.x][tmp.y] = tmp.val;
				q.push(tmp);
			}
		}
		if(check(node.x-1,node.y)){
			SET_NODE(tmp,node.x-1,node.y,node.val+len);
			if(tmp.val<dis[tmp.x][tmp.y])
			{
				dis[tmp.x][tmp.y] = tmp.val;
				q.push(tmp);
			}
		}
		if(check(node.x,node.y+1)){
			SET_NODE(tmp,node.x,node.y+1,node.val+1);
			if(tmp.val<dis[tmp.x][tmp.y])
			{
				dis[tmp.x][tmp.y] = tmp.val;
				q.push(tmp);
			}
		}
		if(check(node.x,node.y-1)){
			SET_NODE(tmp,node.x,node.y-1,node.val+1);
			if(tmp.val<dis[tmp.x][tmp.y])
			{
				dis[tmp.x][tmp.y] = tmp.val;
				q.push(tmp);
			}
		}
	}
	return 0;
}
void Solve()
{
	int i,j,k,t,tt;

	scanf("%d",&tt);
	rep(t,1,tt+1){
		scanf("%lf%d",&dist,&n);
		rep(i,0,n)
		{
		getchar();
			gets(&g[i][0]);
		}
		m = strlen(g[0]);
		rep(i,0,n)
			rep(j,0,m)
				if(g[i][j]==‘S‘)
				{
					s.x = i;
					s.y = j;
				}else if (g[i][j]==‘E‘)
				{
					e.x = i;
					e.y = j;
				}
		s.val = 0;

		double low = 0;
		double high = 10;
		double mid = (low+high)/2;
		double res = 0;
		while(ABS(low-high)>EPS)
		{
			mid = (low+high)/2;
			res = BFS(mid);
			//printf("[%f %f %f]\n",mid,res,dist);
			if(res < dist+EPS)
				low = mid ;
			else
				high = mid;
		}
		printf("Case #%d: %.3f%%\n",t,mid*100);
	}
}
int main()
{
	Solve();
	return 0;
}
时间: 2024-08-27 06:35:40

{POJ}{3897}{Maze Stretching}{二分答案+BFS}的相关文章

POJ 2112 Optimal Milking 二分答案+最大流

首先二分最长的边,然后删去所有比当前枚举的值长的边,算最大流,看是否能满足所有的牛都能找到挤奶的地方 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include

POJ 3258 River Hopscotch 二分答案

River Hopscotch Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6193   Accepted: 2685 Description Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. T

POJ 3273 Monthly Expense 二分答案

Monthly Expense Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13281   Accepted: 5362 Description Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and r

POJ 3484 Showstopper(二分答案)

[题目链接] http://poj.org/problem?id=3484 [题目大意] 给出n个等差数列的首项末项和公差.求在数列中出现奇数次的数.题目保证至多只有一个数符合要求. [题解] 因为只有一个数符合要求,所以在数列中数出现次数的前缀和必定有奇偶分界线, 所以我们二分答案,计算前缀和的奇偶性进行判断,得到该数的位置. [代码] #include <cstdio> #include <algorithm> #include <cstring> using na

POJ 3579 Median(二分答案+Two pointers)

[题目链接] http://poj.org/problem?id=3579 [题目大意] 给出一个数列,求两两差值绝对值的中位数. [题解] 因为如果直接计算中位数的话,数量过于庞大,难以有效计算, 所以考虑二分答案,对于假定的数据,判断是否能成为中位数 此外还要使得答案尽可能小,因为最小的满足是中位数的答案,才会是原差值数列中出现过的数 对于判定是不是差值的中位数的过程,我们用尺取法实现. 对于差值类的题目,还应注意考虑边界,即数列只有一位数的情况. [代码] #include <cstdio

POJ 3208 Apocalypse Someday 二分答案+数位DP

这题应该是POJ最强大的一道数位DP了吧 正解是AC自动机 不会 还是写数位DP吧 题目大意:我们令含有666的数字为不吉利数字,则可以得到一个递增数列: {an}=666,1666,2666,3666,4666,5666,6660,6661,.... 给定n,求an 首先我们把这个问题转化成另一个问题:给定n,求1~n中有多少个数含有666 解决了这个问题,把原问题二分答案即可 首先预处理f数组,令 f[i][0]表示i位数中首位不为6且不含666的数的数量 f[i][1]表示i位数中首位连续

POJ 1064 Cable master (二分答案)

题目链接:http://poj.org/problem?id=1064 有n条绳子,长度分别是Li.问你要是从中切出m条长度相同的绳子,问你这m条绳子每条最长是多少. 二分答案,尤其注意精度问题.我觉得关于浮点数的二分for循环比while循环更好一点.注意最后要用到floor 保证最后答案不会四舍五入. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 using namespace std;

POJ 2773 Happy 2006 (二分答案+容斥)

题目链接:http://poj.org/problem?id=2773 题意: 求第k个与m互质的数: 分析: 很明显随着数的增大与m互质的数就越多,因此我们可以二分答案, 中间需要用到容斥原理求[1,mid]内与m互质的数的个数: 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <vector> using namespace std; const int ma

POJ 1759 Garland(二分答案)

[题目链接] http://poj.org/problem?id=1759 [题目大意] 有n个数字H,H[i]=(H[i-1]+H[i+1])/2-1,已知H[1],求最大H[n], 使得所有的H均大于0. [题解] 我们得到递推式子H[i]=2*H[i-1]+2-H[i-2],发现H[n]和H[2]成正相关 所以我们只要二分H[2]的取值,同时计算每个H是否大于等于0即可. [代码] #include <cstdio> int n; double H[1010],A,B; bool che