• 状压dpHDU


    J - Tunnels HDU - 4856 

      题目大意:地图上有些管道,在管道行走里不需要花费时间,但从一个管道的出口走到另一个管道的入口则需要花费时间,问走完所有管道最短的时间,如果不行,则输出-1.

      先用bfs处理出每两个点之间的距离,这样就可以知道每个管道出口到其他出口的距离,然后就是怎么走这些管道,如果直接深搜有15!种情况,肯定不行,而n,m最大都才15,总状态一共就215-1个,这样我们枚举每个状态,然后再枚举这个状态已经走过的管道,最后枚举这个状态没走到的管道,dp[i][j]就代表i状态最后走的是j管道的最短时间。 

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 using namespace std;
     5 const int inf=0x3f3f3f3f;
     6 const int ne[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
     7 struct Node{
     8     int x,y,t;
     9     Node(){}
    10     Node(int x,int y,int t):x(x),y(y),t(t){}
    11 };
    12 int n,m,sn,ans,dis[20][20][20][20],vis[20][20];
    13 int x1[20],y1[20],x2[20],y2[20],dp[1<<18][20],cf2[18]={1};
    14 char s[20][20];
    15 void bfs(int x,int y)
    16 {
    17     memset(vis,0,sizeof(vis));
    18     vis[x][y]=1;
    19     queue<Node> q;
    20     q.push(Node(x,y,0));
    21     while(!q.empty())
    22     {
    23         Node p=q.front();
    24         q.pop();
    25         dis[x][y][p.x][p.y]=p.t;
    26         for(int i=0;i<4;i++)
    27         {
    28             int dx=p.x+ne[i][0];
    29             int dy=p.y+ne[i][1];
    30             if(dx<=0||dx>n||dy<=0||dy>n)
    31                 continue;
    32             if(!vis[dx][dy]&&s[dx][dy]!='#')
    33             {
    34                 vis[dx][dy]=1;
    35                 q.push(Node(dx,dy,p.t+1));
    36             }
    37         }
    38     }
    39 }
    40 int main()
    41 {
    42     for(int i=1;i<=15;i++)
    43         cf2[i]=cf2[i-1]<<1;
    44     while(~scanf("%d%d",&n,&m))
    45     {
    46         memset(dp,inf,sizeof(dp));
    47         memset(dis,inf,sizeof(dis));
    48         for(int i=1;i<=n;i++)
    49             scanf("%s",s[i]+1);
    50         for(int i=1;i<=n;i++)
    51             for(int j=1;j<=n;j++)
    52                 bfs(i,j);//预处理出距离        
    53         for(int i=0;i<m;i++)
    54             scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
    55         for(int i=0;i<m;i++)
    56             dp[1<<i][i]=0;//第一个走的管道不需要花费时间 
    57         int maxm=(1<<m)-1;
    58         for(int i=1;i<maxm;i++)
    59         {
    60             for(int j=0;j<m;j++)
    61             {
    62                 if(i&cf2[j])//枚举已经走了的 
    63                 {
    64                     for(int k=0;k<m;k++)
    65                         if(!(i&cf2[k]))//枚举还没走的 
    66                             dp[i+cf2[k]][k]=min(dp[i+cf2[k]][k],dp[i][j]+dis[x2[j]][y2[j]][x1[k]][y1[k]]);
    67                 }
    68             }
    69         }
    70         int ans=inf;
    71         for(int i=0;i<m;i++)
    72             ans=min(ans,dp[maxm][i]);
    73         if(ans>=inf)
    74             printf("%d
    ",-1);
    75         else
    76             printf("%d
    ",ans);
    77     }
    78     return 0;
    79 }
    马里奥
  • 相关阅读:
    [转载] $CF652B$ 题解
    [转载] $Luogu$ $P4951$ 题解
    luoguP3723 HNOI2017 礼物
    动态dp学习笔记
    noip级别模板小复习
    noip2017简要题解。
    noip考前抱佛脚 数论小总结
    HDU 6071 Lazy Running
    POI2012 ODL-Distance
    [NOI2002]荒岛野人
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/10740214.html
Copyright © 2020-2023  润新知