BZOJ 1295 SCOI 2009 最长距离 SPFA

题目大意:给出一张地图,上面有些点有障碍物,现在有T个机会能够移除障碍物,问地图上最长的欧几里得距离是多长。

思路:在原图的基础上建图,f[i]表示的是起点到这里最少需要移除多少个障碍物,然后暴力枚举起点,更新答案即可。

CODE:

#include <map>
#include <queue>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 10010
using namespace std;
const int dx[] = {0,1,-1,0,0};
const int dy[] = {0,0,0,1,-1};

map<int,pair<int,int> > G;

int m,n,k;
int head[MAX],total;
int next[MAX],aim[MAX];
bool is_block[MAX];

int f[MAX];
bool v[MAX];

char src[110][110];
int num[110][110],cnt;

inline void Add(int x,int y)
{
	next[++total] = head[x];
	aim[total] = y;
	head[x] = total;
}

inline void SPFA(int start)
{
	static queue<int> q;
	while(!q.empty())	q.pop();
	q.push(start);
	memset(v,false,sizeof(v));
	memset(f,0x3f,sizeof(f));
	f[start] = is_block[start];
	while(!q.empty()) {
		int x = q.front(); q.pop();
		v[x] = false;
		for(int i = head[x]; i; i = next[i])
			if(f[aim[i]] > f[x] + is_block[aim[i]]) {
				f[aim[i]] = f[x] + is_block[aim[i]];
				if(!v[aim[i]]) {
					v[aim[i]] = true;
					q.push(aim[i]);
				}
			}
	}
}

inline double Calc(pair<int,int> p1,pair<int,int> p2)
{
	return sqrt((double)(p1.first - p2.first) * (p1.first - p2.first) + (double)(p1.second - p2.second) * (p1.second - p2.second));
}

int main()
{
	cin >> m >> n >> k;
	for(int i = 1; i <= m; ++i) {
		scanf("%s",src[i] + 1);
		for(int j = 1; j <= n; ++j) {
			num[i][j] = ++cnt;
			G[cnt] = make_pair(i,j);
			if(src[i][j] == '1')
				is_block[cnt] = true;
		}
	}
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= n; ++j)
			for(int k = 1; k <= 4; ++k) {
				int fx = i + dx[k];
				int fy = j + dy[k];
				if(!num[fx][fy])	continue;
				Add(num[i][j],num[fx][fy]);
				Add(num[fx][fy],num[i][j]);
			}
	double ans = .0;
	for(int i = 1; i <= cnt; ++i) {
		SPFA(i);
		for(int j = 1; j <= cnt; ++j)
			if(f[j] <= k)
				ans = max(ans,Calc(G[i],G[j]));
	}
	cout << fixed << setprecision(6) << ans << endl;
	return 0;
}

时间: 2024-08-10 21:12:13

BZOJ 1295 SCOI 2009 最长距离 SPFA的相关文章

【BZOJ 1295】 [SCOI2009]最长距离

1295: [SCOI2009]最长距离 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 945  Solved: 492 [Submit][Status][Discuss] Description windy有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格子A不可以走到格子B,就没有距离. 如果格子X和格子Y有公共边,并且X和Y

[BZOJ 1026] [SCOI 2009] Windy数 【数位DP】

题目链接:BZOJ - 1026 题目分析 这道题是一道数位DP的基础题,对于完全不会数位DP的我来说也是难题.. 对于询问 [a,b] 的区间的答案,我们对询问进行差分,求 [0,b] - [0,a-1] 的答案.这样就化繁为简了. 具体过程见代码中的注释. 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath>

BZOJ 1179 APIO 2009 Atm Tarjan+SPFA

题目大意:给出一张有向图,每一个节点有一个权值,经过一次之后会取走节点上的权值.有一个原点,多个汇点,问最多能收获多少权值. 思路:做一次Tarjan将图变成拓扑图,然后直接跑SPFA+Heap,比较慢,但是用了高大上的namespace,很开心. CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>

[BZOJ 1297][SCOI 2009]迷路(矩阵快速幂)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1297 分析:如果每条边的边权都是1,那么就相当于对邻接矩阵自乘T次(因为写一下递推式子f[i][j]=∑f[i][k]*f[k][j]等价于矩阵乘法的定义).但是这题每条边的边权是1~9. 所以可以把每个点i拆成9个点形成链状:i9->i8->i7->i6->i5->i4->i3->i2->i1 (这条链中每条边的长度都为1) 然后对于原图中的

[BZOJ 1026][SCOI 2009]windy数(数位DP)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1026 很基础的数位DP题,很早之前我就尝试做这题,不过当时我被这题吓死了,现在回过头做这题,感觉简单多了. 做这个题时我想到了POJ一道类似的组合数学的题,同样是按数位统计,有异曲同工之妙. 题目要求[a,b]区间上的windy数个数,我们可以转化成求[1,a]上的windy数个数-[1,b-1]上的windy数个数.题目转化成了求[1,x]上的windy数个数,我们就写个函数c

BZOJ 1024 SCOI 2009 生日快乐 深搜

题目大意:有一块蛋糕,长为X,宽为Y.如今有n个人来分这块蛋糕,还要保证每一个人分的蛋糕的面积相等.求一种分法,使得全部的蛋糕的长边与短边的比值的最大值最小. 思路:刚拿到这个题并没有什么思路.可是定睛一看.(n <= 10),额..能够乱搞了... 直接爆搜就能够水过.传三个參数,代表当前的长和宽,还有当前块须要被分成几块,然后随便乱搞就能够水过了.. CODE: #include <cstdio> #include <cstring> #include <ioman

[BZOJ 1879][SDOI 2009]Bill的挑战 题解(状压DP)

[BZOJ 1879][SDOI 2009]Bill的挑战 Description Solution 1.考虑状压的方式. 方案1:如果我们把每一个字符串压起来,用一个布尔数组表示与每一个字母的匹配关系,那么空间为26^50,爆内存: 方案2:把每一个串压起来,多开一维记录匹配字符,那么空间为nlen26,合法,但不便于状态的设计和转移: 方案3:把每一个串同一个位置的字符放在一起,用一个布尔数组记录与每一个小写字母的匹配关系,那么空间为26^15*len,爆内存: 方案4:把每一个串同一个位置

[BZOJ 1295][SCOI2009]最长距离(SPFA+暴力)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1295 分析:很巧妙的一道spfa从搜索的角度是搜索在所有1中搜索删除哪T个1,对整个图询问,这样肯定TLE 不妨反过来想一想:对于两个点,弄出联通这两个点所需删除的最少的1,那么就知道这两个点是否可以作为题目要求的起点和终点,如果满足算一下结果和ans比较一下就可以. 所以算法就出来了: 枚举起点(S,T),用SPFA跑出图上的所有点到起点这条路径联通的最少删除的1,那么ans=max(di

BZOJ 1295 SCOI2009 最长距离 SPFA+暴力

题目大意:给定一个棋盘,一些格子上有障碍物,可以移除T个障碍物,求移除后所有能互相到达的点对中的最大欧几里得距离 m,n<=30,900个点,我们可以枚举起始点,跑一遍SPFA,求出所有经过不超过T个障碍物可达的点,统计ans即可 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 40 usi