zoukankan      html  css  js  c++  java
  • poj 3311(状态压缩DP)

    poj  3311(状态压缩DP)

    题意:一个人送披萨从原点出发,每次不超过10个地方,每个地方可以重复走,给出这些地方之间的时间,求送完披萨回到原点的最小时间。

    解析:类似TSP问题,但是每个点可以重复走,先用floyd预处理每个点两两之间的最短距离,然后用状态压缩DP求出走完所有点后回到原点的最短距离,用一个二进制数表示城市是否走过。

    状态表示:dp[i][j]表示到达j点状态为i的最短距离

    状态转移方程:dp[i][j]=min(dp[i][j],dp[j'][k]+dis[k][j]),dis[k][j]为k到j的最短距离,dp[j'][k]为到达k的没经过j所有状态的最短距离

    DP边界条件:dp[i][j]=dp[0][i],i是只经过j的状态

    枚举所有的状态,求解dp[i][j],然后再枚举走完所有的地方后的状态,求min(dp[(1<<n)-1][j]+dis[j][0])就行了

    AC代码如下:

     1 #include<stdio.h>
     2 #define INF 0x7fffffff
     3 int dp[1<<11][11],n,dis[11][11];
     4 void floyd()
     5 {
     6     int i,j,k;
     7     for(k=0;k<=n;k++)
     8         for(i=0;i<=n;i++)
     9             for(j=0;j<=n;j++)
    10                 if(dis[i][j]>dis[i][k]+dis[k][j])
    11                     dis[i][j]=dis[i][k]+dis[k][j];
    12 }
    13 int min(int a,int b)
    14 {
    15     return a<b?a:b;
    16 }
    17 void DP()
    18 {
    19     int i,j,k;
    20     for(i=0;i< (1<<n);i++)      //枚举所有的状态
    21     {
    22         for(j=1;j<=n;j++)
    23             if(i==(1<<(j-1)))    //状态i中只走过城市j
    24                 dp[i][j]=dis[0][j];
    25             else
    26             {
    27                 if(i&(1<<(j-1)))    //状态i中走过城市j和其他城市
    28                 {
    29                     dp[i][j]=INF;
    30                     for(k=1;k<=n;k++)
    31                     {
    32                         if(j!=k && (i&(1<<(k-1))))    //枚举不是城市j的其他城市
    33                                  //在没经过城市j的状态中,寻找合适的中间点k使得距离更短
    34                             dp[i][j]=min(dp[i][j],dp[i^(1<<(j-1))][k]+dis[k][j]);
    35                     }
    36                 }
    37             }
    38     }
    39     int ans=INF;
    40     for(i=1;i<=n;i++)     //枚举走完所有城市的状态,求回到原点的最短的距离
    41         ans=min(ans,dp[(1<<n)-1][i]+dis[i][0]);
    42     printf("%d
    ",ans);
    43 }
    44 int main()
    45 {
    46     int i,j;
    47     while(scanf("%d",&n)&&n)
    48     {
    49         for(i=0;i<=n;i++)
    50             for(j=0;j<=n;j++)
    51                 scanf("%d",&dis[i][j]);
    52         floyd();   //预处理求出每个点两两之间的最短距离
    53         DP();
    54     }
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    python 多进程下的日志打印
    卷积神经网络思考点,卷积网络就是很多个小分类器构建的网络
    ShuffleNetV1 paper reading
    find,grep,mv 组合使用,对大量数据切割方便
    常用的开源协议
    python3 日志重复打印logger
    pytorch clamp 与clamp_区别
    version GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time reference
    pytorch,cuda8,torch.cuda.is_available return flase (ubuntu14)
    opencv remap 函数
  • 原文地址:https://www.cnblogs.com/frog112111/p/3237356.html
Copyright © 2011-2022 走看看