zoukankan      html  css  js  c++  java
  • bzoj1698 / P1606 [USACO07FEB]白银莲花池Lilypad Pond

    P1606 [USACO07FEB]白银莲花池Lilypad Pond

    转化为最短路求解

    放置莲花的方法如果直接算会有重复情况。

    于是我们可以先预处理和已有莲花之间直接互相可达的点,将它们连边(对,忽略它们)。

    于是剩下的就是边权为1的边了。

    酱紫我们就成功转化为了边权问题。

    蓝后跑跑最短路顺便计个数就解决了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 #define N 50
     7 #define inf 2e9
     8 typedef long long ll;
     9 struct data{
    10     int d,u;
    11     data(){}
    12     data(int A,int B):
    13         d(A),u(B){}
    14     bool operator < (const data &tmp) const{
    15         return d>tmp.d;
    16     }
    17 };priority_queue <data> h;
    18 const int d1[8]={2,2,-2,-2,1,-1,1,-1};
    19 const int d2[8]={-1,1,-1,1,2,2,-2,-2};
    20 int n,m,S,T,id[N][N],e[N][N],d[N*N];
    21 int cnt,hd[N*N],nxt[100009],ed[N*N],poi[100000];
    22 bool vis[N][N]; ll t[N*N];
    23 void adde(int x,int y){
    24     nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
    25     ed[x]=cnt; poi[cnt]=y;
    26 }
    27 void draw(int tt,int x,int y){
    28     vis[x][y]=1;
    29     for(int i=0,r1,r2;i<8;++i){
    30         r1=x+d1[i],r2=y+d2[i];
    31         if(r1<1||r1>n||r2<1||r2>m||vis[r1][r2]) continue;
    32         if(e[r1][r2]==1) draw(tt,r1,r2);
    33         else vis[r1][r2]=1,adde(tt,id[r1][r2]);
    34     }
    35 }
    36 int main(){
    37     scanf("%d%d",&n,&m);
    38     for(int i=1,r=0;i<=n;++i)
    39         for(int j=1;j<=m;++j){
    40             scanf("%d",&e[i][j]);
    41             id[i][j]=++r; d[r]=inf;
    42             if(e[i][j]==3) S=r;
    43             if(e[i][j]==4) T=r;
    44         }
    45     for(int i=1;i<=n;++i)
    46         for(int j=1;j<=m;++j)
    47             if(e[i][j]==0||e[i][j]==3){
    48                 memset(vis,0,sizeof(vis));
    49                 draw(id[i][j],i,j);//没有莲花:就和其他所有与该点之间只要加一朵莲花就可达的点,连一条边权1的边。
    50             }
    51     h.push(data(d[S]=0,S)); t[S]=1;
    52     while(!h.empty()){
    53         data x=h.top(); h.pop();
    54         if(x.d!=d[x.u]) continue;
    55         for(int i=hd[x.u];i;i=nxt[i]){
    56             int to=poi[i];
    57             if(d[to]==d[x.u]+1){
    58                 t[to]+=t[x.u];
    59             }else if(d[to]>d[x.u]+1){
    60                 d[to]=d[x.u]+1;
    61                 t[to]=t[x.u];
    62                 h.push(data(d[to],to));
    63             }
    64         }
    65     }
    66     if(d[T]==inf) printf("-1");
    67     else printf("%d
    %lld",d[T]-1,t[T]);//减去终点多算的一朵
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    你可能不知道的 transition 技巧与细节
    CSS奇思妙想 -- 使用 CSS 创造艺术
    生僻标签 fieldset 与 legend 的妙用
    CSS 奇思妙想边框动画
    (转)linux命令-- pstack命令(跟踪进程栈)
    (转)PostgreSQL 数据库错误代码解释
    postgresql灾备切换
    (转)postgresql配置参数和概念解释
    (转)PostgreSQL跨库操作Oracle利器-Oracle_fdw
    (转)PG运维常用知识点小结
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10058009.html
Copyright © 2011-2022 走看看