[codevs2800]送外卖
[codevs2800]送外卖
试题描述
有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上。n个不同的客户分别在1~n个编号的城市中。送外卖的从0号城市出发,然后n个城市都要走一次(一个城市可以走多次),最后还要回到0点(他的单位),请问最短时间是多少。现在已知任意两个城市的直接通路的时间。
输入
第一行一个正整数n (1<=n<=15)
接下来是一个(n+1)*(n+1)的矩阵,矩阵中的数均为不超过10000的正整数。矩阵的i行j列表示第i-1号城市和j-1号城市之间直接通路的时间。当然城市a到城市b的直接通路时间和城市b到城市a的直接通路时间不一定相同,也就是说道路都是单向的。
输出
一个正整数表示最少花费的时间
输入示例
3 0 1 10 10 1 0 1 2 10 1 0 10 10 2 10 0
输出示例
8
数据规模及约定
1<=n<=15
题解
floyd 预处理之后状压 dp。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x * f; } #define maxn 20 #define maxs 65536 #define oo 2147483647 int n, A[maxn][maxn], f[maxs][maxn]; void up(int& a, int b) { a = min(a, b); return ; } int main() { scanf("%d", &n); for(int i = 0; i <= n; i++) for(int j = 0; j <= n; j++) scanf("%d", &A[i][j]); for(int k = 0; k <= n; k++) for(int i = 0; i <= n; i++) for(int j = 0; j <= n; j++) up(A[i][j], A[i][k] + A[k][j]); int all = (1 << n + 1) - 1; for(int S = 0; S <= all; S++) for(int u = 0; u <= n; u++) f[S][u] = oo; f[1][0] = 0; for(int S = 1; S <= all; S++) for(int u = 0; u <= n; u++) if(f[S][u] < oo) for(int v = 0; v <= n; v++) up(f[S|(1<<v)][v], f[S][u] + A[u][v]); printf("%d\n", f[all][0]); return 0; }
sb codevs 最后一组数据只给了 n*n 的矩阵,而不是 (n+1)*(n+1) 的矩阵,只能用 scanf 过。。。