bzoj2346[Baltic 2011]Lamp*

bzoj2346[Baltic 2011]Lamp

题意:

给出一个像下图一样的电路图,长为n,宽为m,求最少将几个"\"改成"/"或将"/"改成"\"使左上角和左下角联通。n,m<=500

题解:

如果某格是/,则左上角和右下角连边,长度为0,左下角和右上角连边,长度为1;如果某格是\,则左上角和右下角连边,长度为1,左下角和右上角连边,长度为0,然后求最短路即可。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define maxn 300010
 7 #define INF 0x3fffffff
 8 using namespace std;
 9 
10 char str[maxn]; struct e{int t,w,n;}es[maxn*4]; int g[maxn],ess;
11 void pe(int f,int t,int w){
12     es[++ess]=(e){t,w,g[f]}; g[f]=ess; es[++ess]=(e){f,w,g[t]}; g[t]=ess;
13 }
14 int n,m;
15 struct nd{int d,u; bool operator < (const nd &a)const{return d>a.d;}};
16 int d[maxn]; bool vis[maxn]; priority_queue<nd>q;
17 void dijkstra(int s,int t){
18     inc(i,s,t)d[i]=INF; d[s]=0; q.push((nd){0,s});
19     while(!q.empty()){
20         int x; while(!q.empty()&&vis[x=q.top().u])q.pop(); if(vis[x])break; vis[x]=1;
21         for(int i=g[x];i;i=es[i].n)if(d[es[i].t]>d[x]+es[i].w){
22             d[es[i].t]=d[x]+es[i].w; q.push((nd){d[es[i].t],es[i].t});
23         }
24     }
25 }
26 int main(){
27     scanf("%d",&n); scanf("%d",&m);
28     inc(i,1,n){
29         scanf("%s",str+1);
30         inc(j,1,m){
31             if(str[j]=='\\')pe((i-1)*(m+1)+j,i*(m+1)+j+1,0),pe((i-1)*(m+1)+j+1,i*(m+1)+j,1);
32             else pe((i-1)*(m+1)+j,i*(m+1)+j+1,1),pe((i-1)*(m+1)+j+1,i*(m+1)+j,0);
33         }
34     }
35     dijkstra(1,(n+1)*(m+1));
36     d[(n+1)*(m+1)]==INF?printf("NO SOLUTION"):printf("%d",d[(n+1)*(m+1)]); return 0;
37 }

 

20161111

转载于:https://www.cnblogs.com/YuanZiming/p/6058837.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值