• POJ 3311 Hie with the Pie


    链接

    题意:

      n+1个点,求从0开始,走完所有的点,再回到0号点的最小距离。

    思路

      状压dp。首先Floyd预处理出任意两个点之间的距离。dp[s][i]表示走过的点的状态是s,其中到达i点的最小距离(i点属于走过的点,即s状态下的点)。当然s是二进制数1表示走过,0表示为走过。

      那么dp[s][i]就可以到达非s状态的点j,j点是不属于s状态的点,dp[s|(1<<(j-1))][j] = min(dp[s][i]+dis[i][j]);这是一个“推”的转移方程。

      ”拉“:dp[s][i] = min(dp[s^(1<<(i-1))][j]+dis[j][i])。

    代码

    ”推“的写法:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 
     7 using namespace std;
     8 
     9 const int N = 15;
    10 int dp[35000][N],dis[N][N];
    11 int n;
    12 
    13 inline int read() {
    14     int x = 0,f = 1;char ch = getchar();
    15     for (; !isdigit(ch); ch=getchar()) if(ch=='-') f=-1;
    16     for (; isdigit(ch); ch=getchar()) x = x*10+ch-'0';
    17     return x * f;
    18 }
    19 void Floyd() {
    20     for (int k=0; k<=n; ++k) 
    21         for (int i=0; i<=n; ++i) 
    22             for (int j=0; j<=n; ++j) 
    23                 dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
    24 }
    25 int main() {
    26     while (~scanf("%d",&n) != EOF && n) {
    27         memset(dis,0x3f,sizeof(dis));
    28         memset(dp,0x3f,sizeof(dp));
    29         for (int i=0; i<=n; ++i) 
    30             for (int j=0; j<=n; ++j) 
    31                 dis[i][j] = read();
    32         Floyd();
    33         int t = (1 << n) - 1;
    34         dp[0][0] = 0;
    35         for (int i=1; i<=n; ++i) dp[(1<<(i-1))][i] = dis[0][i];
    36         for (int s=1; s<=t; ++s) 
    37             for (int i=1; i<=n; ++i) {
    38                 if (s&(1<<(i-1))==0) continue;
    39                 for (int j=1; j<=n; ++j) {
    40                     if (s&(1<<(j-1))) continue;
    41                     dp[s|(1<<(j-1))][j] = min(dp[s|(1<<(j-1))][j],dp[s][i]+dis[i][j]);
    42                 }    
    43             }
    44         
    45         int ans = 1e9;
    46         for (int i=1; i<=n; ++i) {
    47             ans = min(ans,dp[t][i]+dis[i][0]);
    48         }
    49         cout << ans << "
    ";
    50     }
    51     return 0;
    52 }
    View Code

    "拉”的写法

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 
     7 using namespace std;
     8 
     9 const int N = 15;
    10 int dp[35000][N],dis[N][N];
    11 int n;
    12 
    13 inline int read() {
    14     int x = 0,f = 1;char ch = getchar();
    15     for (; !isdigit(ch); ch=getchar()) if(ch=='-') f=-1;
    16     for (; isdigit(ch); ch=getchar()) x = x*10+ch-'0';
    17     return x * f;
    18 }
    19 void Floyd() {
    20     for (int k=0; k<=n; ++k) 
    21         for (int i=0; i<=n; ++i) 
    22             for (int j=0; j<=n; ++j) 
    23                 dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
    24 }
    25 int main() {
    26     while (~scanf("%d",&n) != EOF && n) {
    27         memset(dis,0x3f,sizeof(dis));
    28         memset(dp,0x3f,sizeof(dp));
    29         for (int i=0; i<=n; ++i) 
    30             for (int j=0; j<=n; ++j) 
    31                 dis[i][j] = read();
    32         Floyd();
    33         int t = (1 << n) - 1;
    34         for (int s=0; s<=t; ++s) 
    35             for (int i=1; i<=n; ++i) {
    36                 if (s&(1<<(i-1))==0) continue;
    37                 if (s == (1<<(i-1))) dp[s][i] = dis[0][i];
    38                 else {
    39                     for (int j=1; j<=n; ++j) {
    40                         if (s&(1<<(j-1))==0) continue;
    41                         dp[s][i] = min(dp[s][i],dp[s^(1<<(i-1))][j]+dis[j][i]);
    42                     }
    43                 }    
    44             }
    45         
    46         int ans = 1e9;
    47         for (int i=1; i<=n; ++i) {
    48             ans = min(ans,dp[t][i]+dis[i][0]);
    49         }
    50         cout << ans << "
    ";
    51     }
    52     return 0;
    53 }
    View Code
  • 相关阅读:
    无熟人难办事?—迪米特法则
    考题抄错会做也白搭—模板方法模式
    简历复印—原型模式
    Android Studio 安装及常见问题
    雷锋依然在人间——工厂方法模式
    欢迎测试
    客户端程序设计V1
    Linux服务器端程序设计V1
    【Alpha】最后一篇
    【Alpha】开发日志Day10-0721
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8965799.html
Copyright © 2020-2023  润新知