zoukankan      html  css  js  c++  java
  • lightoj1057

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1057

    题目大意:在二维矩阵中,给你一个起点和至多15个的目标点。要你求出从起点出发经过完所有的点后回到起点的最短路径值。每个点一步可以向 八个方向走。

    算法思路:一看就觉得是tsp,用状态压缩。而任意两点的距离就是相应横纵坐标差的较大值。具体看代码。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 1<<16;
    const int INF = 0x3f3f3f3f;
    
    int dp[16][maxn];  //dp[i][S] 表示从起点走完S中的点到达i的最小距离。
    int m,n;
    struct Point{
        int x,y;
        Point(int x=0,int y=0): x(x), y(y) {}
    }P[16],startP;
    int goldnum;
    int dist[16][16];
    
    inline int myfabs(int a){
        if(a < 0) a = -a;
        return a;
    }
    
    int main()
    {
        //freopen("E:\acm\input.txt","r",stdin);
        int T;
        cin>>T;
    
        for(int cas=1; cas<=T; cas++)
        {
            cin>>m>>n;
            char s[20];
            goldnum = 0;
    
            for(int i=0; i<m; i++)
            {
                scanf("%s",s);
                for(int j=0; j<n; j++)
                {
                    if(s[j] == 'x')
                    {
                        startP = Point(i,j);
                    }
                    else if(s[j] == 'g')
                    {
                        P[goldnum++] = Point(i,j);
                    }
                }
            }  //存点。
            memset(dist,0x3f,sizeof(dist));
            for(int i=0; i<goldnum; i++)
                for(int j=i+1; j<goldnum; j++)
            {
                dist[i][j] = dist[j][i] = max(myfabs(P[j].x-P[i].x),myfabs(P[j].y-P[i].y));  //任意两个gold的距离
            }
            for(int i=0; i<goldnum; i++) //把第goldnum看成起点。求起点与任意一个gold的距离。
            {
                dist[goldnum][i] = dist[i][goldnum] = max(myfabs(startP.x-P[i].x),myfabs(startP.y-P[i].y));
            }
    
            int All = (1<<goldnum) - 1;
            memset(dp,0x3f,sizeof(dp));
            dp[0][0];
            for(int i=0; i<goldnum; i++)
            {
                dp[i][1<<i] = dist[goldnum][i];
            }
            for(int S=1; S<=All; S++)
            {
                for(int i=0; i<goldnum; i++)
                {
                    if(S & (1<<i))  //S中包含了i这点。
                    {
                        for(int j=0; j<goldnum; j++)
                        {
                            if(S & (1<<j)) continue;  //要取不在S中的点j
                            dp[j][S|(1<<j)] = min(dp[j][S|(1<<j)],dp[i][S] + dist[i][j]);
                        }
                    }
                }
            }
            int ans = INF;
            for(int i=0; i<goldnum; i++)
                ans =min(ans,dp[i][All] + dist[i][goldnum]);
    
            if(ans == INF) ans = 0;   //这个坑,WA了几次
            printf("Case %d: %d
    ",cas,ans);
        }
    }
    /**
    Keep in mind that, when you receive a WA and want to find "critical" cases,
    it's often useful to start by thinking of cases that go to either extreme 
    of the specifications (either the largest or lowest numbers possible).
    It doesn't take a lot of practice to get in a frame of mind in which,
    when you read something like "There will be exactly one 'x' in the city 
    and at most 15 gold positions", you almost immediately make the connection to 
    think of a test case with either 0 or 15 gold and try that.
    **/
    View Code
  • 相关阅读:
    C++11: reference_wrapper
    mac 查看目前哪些进程占用哪些端口
    Intellij IDEA 10.5 语言设置
    linux中的strip命令简介------给文件脱衣服
    HashMap的key可以是可变的对象吗???
    java BIO/NIO/AIO 学习
    java 反射
    Java线程同步
    maven modules
    设计模式在cocos2d-x中的使用--简单工厂模式(Simple Factory)
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3330446.html
Copyright © 2011-2022 走看看