[BalticOI 2011 Day1] Switch the Lamp On

题目传送门

第一眼看这题,我问教练:是不是用f[i][j]表示左上角坐标为1,1,右下角坐标为i,j的矩形能否从左上角通到右下角。。。教练用关爱傻逼的眼神看了我一眼就走开了。。。

后来才发现是道最短路。。。Fa♂Q

把每一个格点当做节点(这里编号用二维更方便,我用的一维)

初始状态的连接权值为0,旋转的之后的连接权值为1

跑一遍dij堆优化orSPFA即可(dij堆优化我吸氧才过的。。。)

代码:.

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt;
int f[5005][5005];
int dis[260005];
int head[260050];
priority_queue<pair<int,int> > q;
struct edge
{
    int v,w,nxt;
}e[20000005];
void add(int u,int v,int w)
{
    cnt++;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
int main()
{
    memset(dis,127,sizeof(dis));
    cin>>n>>m;
    int js=0;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
        {
            js++;
            f[i][j]=js;
        }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            char c;
            cin>>c;
            if(c=='/')
            {
                add(f[i-1][j],f[i][j-1],0);
                add(f[i][j-1],f[i-1][j],0);
                add(f[i-1][j-1],f[i][j],1);
                add(f[i][j],f[i-1][j-1],1);
            }
            if(c=='\\')
            {
                add(f[i-1][j],f[i][j-1],1);
                add(f[i][j-1],f[i-1][j],1);
                add(f[i-1][j-1],f[i][j],0);
                add(f[i][j],f[i-1][j-1],0);
            }
        }
        getchar();
    }
    dis[1]=0;
    q.push(make_pair(0,1));
    while(!q.empty())
    {
        int u=q.top().second;
        q.pop();
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(dis[u]+e[i].w<dis[v])
            {
                dis[v]=dis[u]+e[i].w;
                q.push(make_pair(-dis[v],v));
            }
        }
    }
    if(dis[js]<100000000) cout<<dis[js];
    else cout<<"NO SOLUTION";
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ssf-xiaoban/p/11625481.html