UVa 1078 Steam Roller

借鉴了陈峰在训练指南的思路, 表示感谢

提示: 1. 直接求最短路是有困难的, 因为状态不满足独立性 , 所以拆点

    2. 将(x , y)细分成 , (x , y , dir , doubled)  , 后两个分别为到这个点时的方向、这条边是否两次计算了

    3. 将每一个状态用一个id 函数投射到一个具体的数值 , 然后预处理所有状态之间的边(处理好那些double) , 这样求最短路就是一个独立的过程

    4. 开头的源点不好把握 , 所以特殊处理 , 将第一次转移拿出来 ; 但结尾的统计是简单的


注意: 为了方便各种mod , 和计算id , 使用从0开始的坐标会更简单 , 如果有人看过训练指南的代码仓库这个题的代码 , 就会发现写的很麻烦 , 这种题目一定要注意 , 充分利用状态 , 不要给自己添麻烦 , 详情见代码


//
//  main.cpp
//  UVa 1078
//
//  Created by Fuxey on 15/10/7.
//  Copyright © 2015年 corn.crimsonresearch. All rights reserved.
//

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
struct edge
{
    int t , v;
    edge(int t = 0, int v = 0):t(t),v(v){}
};
struct state
{
    int p , d;
    state(int p = 0, int d = 0):p(p),d(d){}
    bool operator <(const state& b)const { return d>b.d; }
};
const int maxnode=  8e4+1e3;
const int INF = 1<<29;
int e[110][110][2];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int rev[]={1,0,3,2};
int n , m , sx , sy , ex , ey;

vector g[maxnode];
int d[maxnode] , book[maxnode];

int id(int x , int y , int i, int j){ if(!(x>=0 && x=0 && ydir , j-?doubled
void reid(int p)
{
    int d = p%2; p/=2; int dir = p%4; p/=4; int y = p%m; int x = p/m;
    cout<>n>>m>>sx>>sy>>ex>>ey && n+m)
    {
        sx--; sy--; ex--; ey--;
        for(int i=0;i q;
        int ss = id(sx, sy, 0, 1);
        for(int i=0;i d[u.p]+v)
                {
                    d[t] = d[u.p]+v;
                    q.push(state(t , d[t]));
                }
            }
        }
        int res = INF;
        for(int dir = 0;dir<4;dir++)
        {
            int p = id(ex, ey, dir, 1);
            res = min(res, d[p]);
        }
        cout<<"Case "<<++Case<<": ";
        if(res==INF) cout<<"Impossible\n";
        else cout<

Ps: 这是最裸的 , 不使用邻接表 , 不手写队列的版本 , 估计都实现可以速度快上两倍 , 有兴趣的可以自己实现

文章有任何纰漏 , 或者有任何问题 , 请告知博主: QQ:812483101 

你可能感兴趣的:(拆点,UVa,最短路,uva,最短路)