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的中数的取值范围的大小
    前端通过xlsx插件导入excel
    H5和安卓原生进行交互的操作流程记录
    javascript中字符串和数字之间互相转换的方法总结
    gitlab代码合并到主分支
    typeof和valueof、instance of 之间的区别
    javascript中map会改变原始的数组吗
    使用typescript来写react遇到的一些问题
    使用javascript进行时间数据格式的转换
    在vue的移动端项目中使用vue-echarts
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3330446.html
Copyright © 2011-2022 走看看