题目1 : 积水的城市
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
如下图所示,某市市区由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 <= 500)
第二行包含N-1个整数, B1, B2, B3, … BN-1。(1 <= Bi <= 100)
第三行包含M-1个整数, A1, A2, A3, … AM-1。(1 <= Ai <= 100)
第四行包含一个整数K,表示积水的交叉口的数目。 (0 <= K <= 30)
以下K行每行包含2个整数,X和Y,表示第X条路和第Y条街的交叉口积水。(1 <= X <= N, 1 <= Y <= M)
第K+5行包含一个整数Q,表示询问的数目。 (1 <= Q <= 10)
以下Q行每行包含4个整数x, y, p, q,表示小Ho的起止点。起止点保证不在积水的交叉口处。 (1 <= x, p <= N, 1 <= y, q <= M)
输出
对于每组询问,输出最短路的长度。如果小Ho不能到达目的地,输出-1。
样例输入
4 5
2 4 1
3 3 3 2
3
1 3
2 3
3 2
1
1 2 2 4
样例输出
24
思路:直接把交叉点的二维坐标映射成一维的点,因为矩阵边长最大值是500所以最多一共有250000个顶点,大约4*250000=1000000条边,这是很稀疏的图,而且邻接矩阵也存不下,于是用邻接表,求最短路套spfa的模板,建图的比较恶心。
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int M = 10000005;
const int INF = 999999999;
struct node
{
int u;
int v;
int c;
}p[M];
int Next[M];
int head[M];
long long dist[M];
bool visit[M];
int now[M];
int e,top;
int a,b;
int n,m,k,x,y,Q,p0,q0;
void addnode(int a,int b,int c)
{
p[e].c = c;
p[e].u = a;
p[e].v = b;
Next[e] = head[a];
head[a] = e++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(Next,-1,sizeof(Next));
e = 0;
}
bool relax(int u,int v,int c)
{
if(dist[v]> dist[u]+c){
dist[v] = dist[u] + c;
return true;
}
return false;
}
void spfa(int t)
{ int j,i;
int num = n*m;
memset(visit,0,sizeof(visit));
for(i=0;i<num;i++){
dist[i] = INF;
}
dist[t] = 0;
visit[t] = true;
queue <int>Q;
Q.push(t);
while(!Q.empty()){
int pre = Q.front();
Q.pop();
visit[pre] = false;
for(int i = head[pre];i+1;i=Next[i] ){
if(relax(pre,p[i].v,p[i].c)&&!visit[p[i].v]){
Q.push(p[i].v);
visit[p[i].v] = true;
}
}
}
}
int G[505][505];
int dir[4][2] = {{0,1},{-1,0},{1,0},{0,-1}};
int main()
{
int A[505];
int B[505];
cin>>n>>m;
int num = n*m;
for(int i = 1; i < n; ++i)
cin>>B[i];
for (int i = 1; i < m; ++i)
cin>>A[i];
for (int i = 0; i < n ; ++i)
for (int j = 0; j < m ; ++j)
G[i][j] = 0;
init();
cin>>k;
for (int i = 0; i < k; ++i){
cin>>x>>y;
G[x-1][y-1] = -1;
}
for (int i = 0; i < n; ++i){
for (int j = 0; j < m; ++j){
if(G[i][j]!= -1 ){
if( i < n-1 && j < m-1 ){
if(G[i][j+1]!=-1){
addnode(i*m+j,i*m+j+1,A[j+1]);
addnode(i*m+j+1,i*m+j,A[j+1]);
}
if(G[i+1][j]!=-1){
addnode(i*m+j,(i+1)*m+j,B[i+1]);
addnode((i+1)*m+j,i*m+j,B[i+1]);
}
}
if(j == m-1 && i <= n-2){
addnode(i*m+j,(i+1)*m+j,B[i+1]);
addnode((i+1)*m+j,i*m+j,B[i+1]);
}
if(i == n-1 && j <= m-2){
addnode(i*m+j,i*m+j+1,A[j+1]);
addnode(i*m+j+1,i*m+j,A[j+1]);
}
}
else{
for(int k = 0; k < 4; ++k){
int dx = i + dir[k][0];
int dy = j + dir[k][1];
if(dx >=0 && dx < n && dy >=0 && dy < m){
addnode(i*m+j,dx*m+dy,INF);
addnode(dx*m+dy,i*m+j,INF);
}
}
}
}
}
cin>>Q;
while(Q--){
cin>>x>>y>>p0>>q0;
int u = (x-1)*m + y-1;
int v = (p0-1)*m + q0-1;
spfa(u);
if(dist[v]<INF)
cout<<dist[v]<<endl;
else
cout <<"-1"<<endl;
}
return 0;
}
上面的代码不知道什么原因一直只有90分,后来看了一下别人的用优先队列优化的BFS觉得代码比较简单,于是学习一波
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int M = 550+5;
const int INF = 100000;
int n,m,k,q;
int a[M],b[M],G[M][M],vis[M][M];
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int dis(int x,int y,int i)
{
if( i == 0) return a[x-1];
if( i == 1) return a[x];
if( i == 2) return b[y-1];
return b[y];
}
typedef struct node
{
int x,y,d;
node(){}
node(int u,int v,int c) : x(u),y(v),d(c){}
node go(int i){
return node(x+dir[i][0],y+dir[i][1],d+dis(x,y,i));
}
bool operator < (const node &s) const{
return d > s.d;
}
bool isok(){
return x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y];
}
};
int main()
{
cin>>n>>m;
for(int i = 1; i < n; ++i)
cin>>a[i];
for(int i = 1; i < m; ++i)
cin>>b[i];
cin>>k;
for(int i = 1; i <= k; ++i){
int x,y;
cin>>x>>y;
vis[x][y] = 1;
}
cin>>q;
while(q--){
fill(G[0], G[550] + 550, INF);
int x, y, s, t;
cin >> x >> y >> s >> t;
G[x][y] = 0;
node start(x,y,0);
priority_queue<node>que;
que.push(start);
while(!que.empty()){
node now = que.top();
que.pop();
for (int i = 0; i < 4; ++i){
node tmp = now.go(i);
if(tmp.isok()){
if(G[tmp.x][tmp.y] > G[now.x][now.y] + dis(now.x,now.y,i)){
G[tmp.x][tmp.y] = G[now.x][now.y] + dis(now.x,now.y,i);
que.push(tmp);
}
}
}
}
if(G[s][t]!=INF) cout <<G[s][t]<<endl;
else
cout<<"-1"<<endl;
}
return 0;
}