关闭

hihocoder

标签: ACMhihocoderspfagraphOffer收割编程练习赛7
349人阅读 评论(0) 收藏 举报
分类:

描述

提示:本题与“积水的城市”相比,数据范围扩大了。

如下图所示,某市市区由M条南北向的大街和N条东西向的道路组成。其中由北向南第i条路和第i+1条路之间的距离是Bi (1 <= i < N),由西向东第i条街和第i+1条街之间的距离是Ai (1 <= i < M)。

小Ho现在位于第x条路和第y条街的交叉口,他的目的地是第p条路和第q条街的交叉口。由于连日降雨,城市中有K个交叉口积水太深不能通行。小Ho想知道到达目的地的最短路径的长度是多少。

输入

第一行包含两个整数N和M。(1 <= N, M <= 1000)  

第二行包含N-1个整数, B1, B2, B3, ... BN-1。(1 <= Bi <= 100000)  

第三行包含M-1个整数, A1, A2, A3, ... AM-1。(1 <= Ai <= 100000)  

第四行包含一个整数K,表示积水的交叉口的数目。 (1 <= K <= 30)  

以下K行每行包含2个整数,X和Y,表示第X条街和第Y条路的交叉口积水。(1 <= X <= N, 1 <= Y <= M)  

第K+5行包含一个整数Q,表示询问的数目。 (1 <= Q <= 1000)  

以下Q行每行包含4个整数x, y, p, q,表示小Ho的起止点。起止点保证不在积水的交叉口处。  (1 <= x, p <= N, 1 <= y, q <= M)

输出

对于每组询问,输出最短路的长度。如果小Ho不能到达目的地,输出-1。


解题思路:可以用简单SPFA去解,明显会超时,由于积水的交叉口的数目很少,可以容易想到,图中某些点肯定不会走到,这样就对图进行压缩,横向和纵向都进行压缩,只走起点和终点并且交叉口的横纵坐标的列并且和他们相邻的列。代码如下:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;

#define MK make_pair

const int inf = 1000000007;
const int N = 1005;
const int M = 1005;

int n,m,block_num;
int dis_n[N],dis_m[M];
int next_l[M],next_r[M],next_l_n[N],next_r_n[N]; // 对图进行压缩

map<int,int> mp; //对图进行压缩使用的数据结构
map<int,int>mp_n;<span style="font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;">//对图进行压缩使用的数据结构</span>

set<pair<int,int> > st;  // 保存积水交叉口

int dis[N][M];//最短路径
int start_n,start_m,end_n,end_m;
int sum_m[M],sum_n[M];  //对距离求和,进行预处理

//判断是否加入队列中
void inline judge(queue<pair<int,int> >& que,int x,int y,int new_dis,int add_dis)
{
	if(1<=x && x <= n && 1 <= y && y <= m && st.find(MK(x,y)) == st.end())
	{
		if(dis[x][y] >  new_dis+ add_dis)
		{
			dis[x][y] = new_dis+ add_dis;
			if(x != end_n || y != end_m)
				que.push(MK(x,y));
		}
	}
}


int SPFA()
{
//对图进行压缩,找上下左右的邻居
	mp[start_m] += 1;
	mp[end_m] += 1;

	mp_n[start_n] += 1;
	mp_n[end_n] += 1;

	int pre_num = 0,current_num;
	map<int,int>::iterator it = mp.begin();
	it++;
	for(;it != mp.end();it++)
	{
		current_num = it->first;
		next_r[pre_num] = current_num;
		next_l[current_num] = pre_num;

		pre_num = current_num;
	}

	pre_num = 0;
	it = mp_n.begin();
	it++;
	for(;it != mp_n.end();it++)
	{
		current_num = it->first;
		next_r_n[pre_num] = current_num;
		next_l_n[current_num] = pre_num;
		pre_num = current_num;
	}


	dis[start_n][start_m] = 0;
	queue<pair<int,int> >que;
	que.push(MK(start_n,start_m));

	int x,y;
	pair<int,int> node;
	while(!que.empty())
	{
		node = que.front();
		que.pop();
		//cout << node.first << ' ' << node.second << endl;
<span style="white-space:pre">		</span>// 下面的点
		x = next_r_n[node.first];
		y = node.second;
		judge(que,x,y,dis[node.first][node.second],sum_n[x - 1] - sum_n[node.first - 1]);
<span style="white-space:pre">		</span>//上面的点
		x = next_l_n[node.first];
		y = node.second;
		judge(que,x,y,dis[node.first][node.second],sum_n[node.first - 1] - sum_n[x - 1]);
<span style="white-space:pre">		</span>//右面的点
		x = node.first;
		y = next_r[node.second];
		judge(que,x,y,dis[node.first][node.second],sum_m[y - 1] - sum_m[node.second - 1]);
<span style="white-space:pre">		</span>//左面的点
		x = node.first;
		y = next_l[node.second];
		judge(que,x,y,dis[node.first][node.second],sum_m[node.second - 1] - sum_m[y - 1]);
		
	}
<span style="white-space:pre">	</span>//删除查询点,避免查询过多的情况下,压缩图没什么效果
	mp[start_m] -= 1;
	mp[end_m] -= 1;
	if(mp[start_m] == 0)
		mp.erase(start_m);
	
	if(mp[end_m] == 0)
		mp.erase(end_m);
	
	mp_n[start_n] -= 1;
	mp_n[end_n] -= 1;
	if(mp_n[start_n] == 0)
		mp_n.erase(start_n);
	
	if(mp_n[end_n] == 0)
		mp_n.erase(end_n);
	
	if(dis[end_n][end_m] != inf)
		return dis[end_n][end_m];
	return -1;
}
int main()
{
	scanf("%d %d",&n,&m);
	sum_n[0] = 0;
	for(int i = 1;i<n;i++)
	{
		scanf("%d",dis_n + i);
		sum_n[i] = sum_n[i -1] + dis_n[i];
	}
	sum_m[0] = 0;
	for(int i = 1;i<m;i++)
	{
		scanf("%d",dis_m + i);
		sum_m[i] = sum_m[i -1] + dis_m[i];
	}

	scanf("%d",&block_num);
	int x,y;
	for(int i = 0;i<block_num;i++)
	{
		scanf("%d %d",&x,&y);
		st.insert(MK(x,y));
		mp[y] = 1;
		if(y >1)
			mp[y - 1] = 1;
		if(y < m)
			mp[y + 1] = 1;
		
		mp_n[x] = 1;
		if(x >1)
			mp_n[x - 1] = 1;
		if(x < n)
			mp_n[x + 1] = 1;
	}
<span style="white-space:pre">	</span>// 加入边界,使程序好处理
	mp[0] = 1;
	mp[m + 1] = 1;
	mp_n[0] = 1;
	mp_n[n + 1] = 1;
	int q;
	scanf("%d",&q);
	for(int i = 0;i<q;i++)
	{
		scanf("%d %d %d %d",&start_n,&start_m,&end_n,&end_m);
		if(start_m > end_m)
		{
			swap(start_n,end_n);
			swap(start_m,end_m);
		}

		for(int j = 0;j<=n;j++)
			for(int k = 0;k<=m;k++)
				dis[j][k] = inf;
		printf("%d\n",SPFA());
	}
	return 0;
}


0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

hihoCoder - 1040 - 矩形判断 (简单计算几何~)

#1040 : 矩形判断 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 给出平面上4条线段,判断这4条线段是否恰好围成一...
  • u014355480
  • u014355480
  • 2015-02-03 14:01
  • 1367

hihoCoder#1032_最长回文子串

求最长回文子串的算法比较经典的是manacher算法,下面写写自己的理解。 (文中用到的图片来自这里,博主写的很好,由于为了图片和代码一致,我稍微p了一下图片。) 首先,说明一下用到的数组和其他参...
  • sinat_30071459
  • sinat_30071459
  • 2016-04-02 19:37
  • 1487

数位DP 浅谈(hihocoder 1033:交错和)

数位DP是一种比较特殊的DP方法,之所以了解到是为了尝试解决hihocoder上一道交错和的题目,更详细的信息请参考这两个文献:文章《浅谈数位类统计问题》 和 讲义《初探数位DP》 事实上在ACM...
  • labud
  • labud
  • 2015-02-03 13:16
  • 5780

hihocoder week1 answer

  • 2014-11-17 21:04
  • 1009B
  • 下载

ACM解题总结——HihoCoder1048

(p.s:第一次做状态压缩dp的题目,真是把俺折腾到死。。。。) 题目来源:    HihoCoder 1048 题目要求:    小Hi和小Ho领到了一个大小为N*M的长方形...
  • octopusflying
  • octopusflying
  • 2016-05-06 10:49
  • 926

hihoCoder #1041 : 国庆出游 ( 深搜,树的遍历 )

题目地址:http://hihocoder.com/problemset/problem/1041时间限制:1000ms 单点时限:1000ms 内存限制:256MB描述 小Hi和小Ho准备国庆...
  • qq_38777624
  • qq_38777624
  • 2017-07-10 14:40
  • 495

hihocoder#1642 : 三角形面积和(思维)

hihocoder#1642 : 三角形面积和(思维)如下图所示,在X轴上方一共有N个等腰直角三角形。这些三角形的斜边与X轴重合,斜边的对顶点坐标是(Xi, Yi)。你能求出这些三角形覆盖的面积之和吗...
  • Mitsuha_
  • Mitsuha_
  • 2017-12-06 22:05
  • 56

HihoCoder 1151 矩阵快速幂 + 取模

传送门:HihoCoder 1151题解 题意 + 递推 同HDU 1143 传送门: HDU 1143解题报告坑点 因为这题n值比较大, 所以和HDU 1143不同, 必须用快速幂取模, ...
  • ADjky
  • ADjky
  • 2016-10-12 13:02
  • 384

hihoCoder:1039字符串消除

题目: 小Hi最近在玩一个字符消除游戏。给定一个只包含大写字母"ABC"的字符串s,消除过程是如下进行的: 1)如果s包含长度超过1的由相同字母组成的子串,那么这些子串会被同时消除,余下的子串...
  • KangRoger
  • KangRoger
  • 2014-12-06 09:49
  • 9217

hihoCoder1080-更为复杂的买卖房屋姿势

1080 : 更为复杂的买卖房屋姿势时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们...
  • algzjh
  • algzjh
  • 2017-07-14 20:07
  • 122
    个人资料
    • 访问:9191次
    • 积分:237
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:0篇
    • 译文:2篇
    • 评论:1条
    最新评论