E - 简单的图论问题? HNCPC 2015年湖南省省赛

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1780
思路:前者可以直接用dijstra算法求出,后者是一个简单的变形。可以将每个点“拆分“成4个不同方向的点,然后用dijstra求出。

#include<cstdio>
#include<queue>
#include<iostream>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<stack>
#include<algorithm>
#define cle(a) memset(a,0,sizeof(a))
#define inf(a) memset(a,0x3f,sizeof(a))
#define ll long long
#define Rep(i,a,n) for(int i=a;i<=n;i++)
using namespace std;
const int INF = ( 2e9 ) + 2;
const ll maxn = 510;
int mp[maxn][maxn];
int d[maxn][maxn][4];
int vis[maxn][maxn];
int Move[]= {1,0,-1,0,1};
int n,m,r1,c1,r2,c2;
struct node
{
    int x,y;
    int d;
    bool operator < (const node &b)const
    {
        return this->d>b.d;
    }
};
struct dot
{
    int x,y,dir;
    int d;
    bool operator < (const dot &b)const
    {
        return this->d>b.d;
    }
};
bool check(int dx,int dy)
{
    return dx>=1&&dx<=n&&dy>=1&&dy<=m;
}
void dijstra2() // 从起点开始 
{
    priority_queue<dot> q;
    q.push(dot{r1,c1,-1,mp[r1][c1]});
    while(!q.empty())
    {
        dot a=q.top();q.pop();
        int x= a.x,y=a.y,dis=a.d,dir=a.dir;
//      cout<<x<<" "<<y<<" "<<dir<<" "<<dis<<endl;
        for(int i=0; i<4; i++)
        {
            int dx=x+Move[i];
            int dy=y+Move[i+1];
            if(dir==i)continue;
            if(check(dx,dy)&&mp[dx][dy]!=-1&&d[dx][dy][i]>dis+mp[dx][dy])
            {
                d[dx][dy][i]=dis+mp[dx][dy];
                q.push(dot{dx,dy,i,d[dx][dy][i]});
            }
        }
    }
}
void dijstra()
{
    priority_queue<node> q;
    q.push(node {r2,c2,mp[r2][c2]});
    vis[r2][c2]=mp[r2][c2];
    while(!q.empty())
    {
        node a= q.top();
        q.pop();
        int x=a.x,y=a.y,d=a.d;
        for(int i=0; i<4; i++)
        {
            int dx=x+Move[i];
            int dy=y+Move[i+1];
            if(check(dx,dy)&&mp[dx][dy]!=-1&&vis[dx][dy]>d+mp[dx][dy])
            {
                vis[dx][dy]=mp[dx][dy]+d;
                q.push(node {dx,dy,vis[dx][dy]});
            }
        }
    }
}
int main()
{
//  freopen("in.txt","r",stdin);
    int Cas=0;
    while(~scanf("%d%d%d%d%d%d",&n,&m,&r1,&c1,&r2,&c2))
    {
        char s[20];
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                int temp;
                scanf("%s",s);
                if(s[0]=='*')
                    mp[i][j]=-1;
                else
                {
                    sscanf(s,"%d",&temp);
                    mp[i][j]=temp;
                }
            }
        inf(d);
        inf(vis);
        dijstra();
        dijstra2();

        int ans=INF;
        for(int i=0;i<4;i++)if(ans>d[r2][c2][i])ans=d[r2][c2][i];
        if(ans==1061109567)ans=-1;
        if(vis[r1][c1]==1061109567)vis[r1][c1]=-1;
        cout<<"Case "<<++Cas<<": ";
        cout<<vis[r1][c1]<<" ";
        cout<<ans<<endl;
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值