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
  • 相关阅读:
    Js 30 BOM
    js面向对象
    js模态窗口
    js默认行为(也称默认事件)
    框架的控件隐藏
    20150706 js之定时器
    sublime快捷方式和node.js
    js回调函数2
    Hibernate 多对一
    Hibernate入门之配置文件
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3330446.html
Copyright © 2011-2022 走看看