Skip to content

11088: 【原1088】邮递员小F

题目

题目描述

author: wcy 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1088

Description

因为制造类专业很难在大城市立足,曾经立志振兴中华之工业的小F,果断在本科毕业后转行做了一名光荣的邮递员。

他的任务是每天从总局出发,行走于所管辖区域的若干的邮局,收集所有的信,然后再汇总返回总局。

因为工作繁忙,同一个邮局他每天只希望去一次。

来往于任意两个邮局是有一定代价的。而且为了方便统计,假定来回两条道路上的代价假设是一样的。

现在小F希望你能给出他每天的最优行走方案,使得总的代价最少。

Input Format

输入数据包括两部分。

第一行为邮局数N。

接下来的N行为一个N×N的对称矩阵。矩阵的第i行,第j列元素Aij代表从邮局i到邮局j的消耗的代价。

规定总局的标号为1。

\( 1 \leq N \leq 15 \)

\( 0 \leq Aij \leq 2000 \)

Output Format

共一行,为满足题目要求的最小的代价。

Sample Input

4
0 6 7 9
6 0 6 5
7 6 0 8
9 5 8 0

Sample Output

26

BugenZhao's solution

//
// Created by BugenZhao on 2019/5/17.
//

#include <iostream>
#include <string>

using std::ios, std::cin, std::cout, std::endl, std::string;

unsigned N;
int d[15][15];
const int statusCount = 1U << 16U;
int dp[15][statusCount];

int getBit(unsigned num) {
    unsigned k = 1;
    int ans = 0;
    while (k <= 2 * num) {
        ans += (bool) (num & k);
        k <<= 1U;
    }
    return ans;
}

int getAns(int cur, unsigned status) {
    if (dp[cur][status] != -1) return dp[cur][status];
    if (getBit(status) == 2) {
        dp[cur][status] = d[0][cur];
        return dp[cur][status];
    }

    int ret = 0x7fffffff;
    for (unsigned i = 1; i < N; ++i) {
        if (i == cur) continue;
        if (status & (1U << i)) {
            int ans = getAns(i, status - (1U << cur)) + d[i][cur];
            if (ans < ret) ret = ans;
        }
    }
    dp[cur][status] = ret;
    return ret;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> N;
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            cin >> d[i][j];
        }
    }

    if (N == 1) {
        cout << 0 << endl;
        return 0;
    }

    for (int i = 0; i < 15; ++i) {
        for (int j = 0; j < statusCount; ++j) {
            dp[i][j] = -1;
        }
    }

    int minAns = 0x7fffffff;
    dp[0][1] = 0;
    for (int i = 1; i < N; ++i) {
        int ans = d[0][i] + getAns(i, (1U << N) - 1);
        if (minAns > ans) minAns = ans;
    }
    cout << minAns << endl;
    return 0;

}

FineArtz's solution

/* 邮递员小F */
#include <iostream>
#include <cstring>
using namespace std;

const int INF = 2000000000;

int n;
int a[16][16];
int f[16][32768];

int main(){
    cin >> n;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            cin >> a[i][j];
    if (n == 1){
        cout << 0 << endl;
        return 0;
    }
    for (int i = 1; i <= (1 << n) - 1; i += 2){
        for (int j = 2; j <= n; ++j){
            if (i & (1 << (j - 1))){
                if (i ^ ((1 << (j - 1)) + 1)){
                    f[j][i] = INF;
                    for (int k = 2; k <= n; ++k){
                        if (k != j && i & (1 << (k - 1))){
                            f[j][i] = min(f[j][i], f[k][i ^ (1 << (j - 1))] + a[k][j]);
                        }
                    }
                }
                else
                    f[j][i] = a[1][j];
            }
        }
    }
    int ans = INF;
    for (int i = 2; i <= n; ++i){
        ans = min(ans, f[i][(1 << n) - 1] + a[i][1]);
    }
    cout << ans << endl;
    return 0;
}

ligongzzz's solution

#include <iostream>
using namespace std;

int map_data[20][20] = { 0 };

int mmin(int a, int b) {
    return a < b ? a : b;
}

bool visited[20] = { 0 };
int n;

int dfs(int pos, int m) {
    if (m == n - 1) {
        return map_data[pos][0];
    }
    visited[pos] = true;
    int ans = 999999999;
    for (int i = 0; i < n; ++i) {
        if (i != pos && !visited[i]) {
            auto cur_ans = dfs(i, m + 1) + map_data[pos][i];
            ans = cur_ans < ans ? cur_ans : ans;
        }
    }
    visited[pos] = false;
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n;

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

    /*
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                map_data[i][j] = mmin(map_data[i][j], map_data[i][k] + map_data[k][j]);
            }
        }
    }*/

    cout << dfs(0, 0);

    return 0;
}

yyong119's solution

#include <iostream>
using namespace std;
int n;
int map[16][16];
int cost;
bool flag[16];
 
void dfs(int depth, int temp, int pos) {
 
    if (temp >= cost) return;
    if (depth == n){
        if (temp + map[pos][1] < cost) cost = temp +map[pos][1];
        return;
    }
    for (int i = 2; i <= n; i++)
    if ((!flag[i])&&(i != pos)) {
        flag[i] = true;
        dfs(depth+1, temp + map[pos][i], i);
        flag[i] = false;
    }
}
int main() {
 
    cin>>n;
    cost = 2000 * 15;
 
    for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) {
        cin>>map[i][j];
    }
    dfs(1,0,1);
    cout<<cost;
}