字节19年春招笔试-毕业旅行

题目:小明目前在做一份毕业旅行的规划。打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的花销。给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。

题目解析:找一条从起点出发,遍历所有城市且只遍历一遍,最后返回起点,最小花销是多少?可以看出这是就是求所有城市的遍历顺序,花费最小的遍历顺序就是所求,既是求遍历顺序,可以用状态压缩,一共有O(1<<N)种状态,为了转移到下一个状态,需要知道每种状态下的最后一个遍历城市是什么,所以再加一维状态(状态s下的最后一个遍历城市), dp[s][i]为已经遍历完s中为1的位对应的城市,最后一个遍历城市为i的最少开销;

最初思路:遍历所有城市,以其为起点;然后用状态压缩+bfs,用inque存储每个(s,i)是否在queue中,空间复杂度为(3 * (1<<n)*20),时间复杂度为O(n^3 * 2 ^ n),既会TLE,也会MLE。。。。

优化:思路优化真的难,很难去突破现有的思路。。。这就导致想得出来就想,想不出来就gg了。。。。有一个重要的特征就是不管从哪个城市出发,最短路径都是一样的。证明:已知从城市i出发,最后回到城市i的最短路径为s,有一条更短的遍历路径为从城市j出发回到j,那么该路径也可以是从i出发最后回到i,也就是说从i出发,最后回到i还有一条更短的路径,与先前假设矛盾。(ps:这种有环的题我有点捉急。。。)

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    cin >> n;

    vector<vector<int>> prices(n, vector<int>(n, 0));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> prices[i][j]; 

    int res = INT_MAX;
    vector<vector<int>> stat(1 << n, vector<int>(n, INT_MAX));

    stat[1][0] = 0;
    for (int s = 1; s < (1 << n); s++)
    {
        for (int i = 0; i < n; i++)
        {
            if ((s & (1 << i)) == 0 || stat[s][i] == INT_MAX) continue;

            for (int j = 1; j < n; j++)
            {
                if (s & (1 << j)) continue;
                int ns = s | (1 << j);

                stat[ns][j] = min(stat[ns][j], stat[s][i] + prices[i][j]);
            }
        }
    }


    for (int lc = 1; lc < n; lc++)
    {
        res = min(res, stat[(1 << n) - 1][lc] + prices[lc][0]);
    }

    cout << res << endl;
    return 0;
}

  

原文链接: https://www.cnblogs.com/mychen06/p/12605879.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    字节19年春招笔试-毕业旅行

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/339089

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午11:55
下一篇 2023年3月1日 下午11:56

相关推荐