ACM-售货员难题

Posted 小小小的程序媛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM-售货员难题相关的知识,希望对你有一定的参考价值。

题目描述:售货员的难题
 某乡有n个村庄(1< n < 20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0 < s < 1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为 1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。

输入

村庄数n和各村之间的路程(均是整数)。

输出

最短的路程

样例输入

3	{村庄数}
0 2 1	{村庄1到各村的路程}
1 0 2	{村庄2到各村的路程}
2 1 0	{村庄3到各村的路程}

样例输出

3

思路:就是DFS,但是减枝比较麻烦,还可以用DP。

这种写法超时!!!
// 售货员的难题.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

const int MAX = 100;
int n, ans, vis[MAX], map[MAX][MAX];

void DFS(int pos, int sum, int cnt)
{
    //cout << "pos:" << pos << "\tsum:" << sum << "\tcnt:" << cnt << endl;
    if (cnt == n)
    {
        //cout << "===========end============:" << "sum:" << sum << "\tans:" << ans << endl;
        sum += map[pos][0];
        ans = min(sum, ans);
        return;
    }
    if (sum > ans) return;
    for (int i = 0; i < n; i++)
    {
        if (!vis[i])
        {
            if (sum + map[pos][i] > ans) continue;
            vis[i] = 1;
            DFS(i, sum + map[pos][i], cnt + 1);
            vis[i] = 0;
            
        }
    }

}

int main()
{
    memset(vis, 0, sizeof(vis));
    memset(map, 0, sizeof(map));
    ans = 0x3f3f3f3f;

    string str;
    cin >> n;
    getline(cin, str);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            cin >> map[i][j];
        getline(cin, str);

    }
    
    vis[0] = 1;
    DFS(0, 0,1);

    cout << ans << endl;


    return 0;
}

 

预处理一下就好了。

#include<iostream>
#include<cstdio>
using namespace std;
int n, g[20][20], r[20][20], f[20], ans = 0x7fffffff;
void Dfs(int now, int sum, int dis)
{
    if (dis + r[now][1] >= ans)return; //如果最小距离仍然大于最优解,直接减枝
    if (dis>ans)return;
    if (sum == n)
    {
        ans = min(ans, dis + g[now][1]);
        return;
    }
    for (int i = 1; i <= n; i++)
    if (f[i] == 0)
    {
        f[i] = 1; Dfs(i, sum + 1, dis + g[now][i]); f[i] = 0;
    }
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
        scanf("%d", &g[i][j]), r[i][j] = g[i][j];
    for (int k = 1; k <= n; k++)
    for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
        r[i][j] = min(r[i][j], r[i][k] + r[j][k]); //计算两点之间的最小距离
    f[1] = 1;
    Dfs(1, 1, 0);
    printf("%d\n", ans);
    return 0;
}

 

以上是关于ACM-售货员难题的主要内容,如果未能解决你的问题,请参考以下文章

2596 售货员的难题

2596 售货员的难题 水深搜

codevs 2596 售货员的难题

codevs2596 售货员的难题(状压dp)

洛谷P1171 售货员的难题 Tsp问题

题解P1171 售货员的难题