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
  • 相关阅读:
    法正(17):玄德
    法正(16):舌战
    法正(15):卢氏
    法正(14):寿星
    struts2笔记---struts2的执行过程
    Oracle数据库(一)
    flask的使用(一)
    struts2--笔记(一)
    docker基础(二)
    docker安装及问题处理
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3330446.html
Copyright © 2011-2022 走看看