• hdu 5067 遍历指定点集最小时间


    http://acm.hdu.edu.cn/showproblem.php?pid=5067

    贴题解

    由于Harry的dig machine是无限大的,而装载石头和卸载石头是不费时间的,所以问题可以转化成:从某一点出发,遍历网格上的一些点,每个点至少访问一次需要的最小时间是多少。这就是经典的旅行商问题,考虑到我们必须要遍历的点只有不到10个,可以用状态压缩解决。
    Dp[i][j]表示i状态的点被访问过了,当前停留在点j 需要的最少时间。枚举另一点不在i状态内的点k,从点j节点走向点k,状态转移
    Dp[i|(1k)][k]=min(Dp[i|(1k)][k],Dp[i][j]+Dis(j,k))
    其中Dis(j,k)表示点j与点k的最短距离,这个可以通过坐标O(1)计算得到。若有t个点包含石头,则算法复杂度为O(nm+(t2)(2t))

    状压dp即可

    注意最后如果ans仍为INF说明可能是全0,需输出0,不然WA到死.

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <map>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define RD(x) scanf("%d",&x)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define clr0(x) memset(x,0,sizeof(x))
    #define eps 1e-9
    const double pi = acos(-1.0);
    typedef long long LL;
    const int modo = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int maxn = 55,maxm = 1e4 + 5;
    int n,m,s[maxn][maxn];
    int dp[11][1<<11];
    typedef pair<int , int> p2;
    p2 r[11];
    int dis(p2 a,p2 b)
    {
        return abs(a.first - b.first) + abs(a.second - b.second);
    }
    void solve()
    {
        int mm = 0;
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= m;++j){
                RD(s[i][j]);
                if(s[i][j]){
                    r[mm++] = make_pair(i,j);
                }
            }
        memset(dp,0x3f,sizeof(dp));
        for(int i = 0;i < mm;++i){
            dp[i][1<<i] = abs(r[i].first - 1) + abs(r[i].second - 1);
        }
        //freopen("1.txt","w",stdout);
        for(int j = 1;j < (1<<mm);++j)
        for(int i = 0;i < mm;++i)if(dp[i][j] != INF){
            for(int k = 0;k < mm;++k){
                if(0 == ((1<<k) & j)){
                    dp[k][j | (1<<k)] = min(dp[i][j] + dis(r[i],r[k]) , dp[k][j | (1<<k)]);
                }
            }
        }
        int ans = INF;
        for(int i = 0;i < mm;++i){
            ans = min(ans,dp[i][(1<<mm)-1] + abs(1 - r[i].first) + abs(1 - r[i].second));
        }
        if(ans == INF)
            ans = 0;
        printf("%d
    ",ans);
        return ;
    }
    int main() {
        while(~RD2(n,m)){
            solve();
        }
        return 0;
    
    }
    


  • 相关阅读:
    第九章:switch语句
    第八章:if-else语句
    第七章:运算符及运用
    第六章:名命规范
    事务
    jdbc
    Object
    容器
    Java exception
    Java OO1
  • 原文地址:https://www.cnblogs.com/zibaohun/p/4046791.html
Copyright © 2020-2023  润新知