[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; }