【wikioi】2800 送外卖(状压dp+floyd)

本文通过状压DP算法解决一个外卖配送问题,目标是最小化从起点出发经过所有城市后返回起点所需的最短时间。使用Floyd算法预处理各城市间的最短路径,并采用状态压缩技巧进行优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.wikioi.com/problem/2800/

本题状压莫名其妙的tle了,(按照hzwer大神打的喂,他1000多ms,我就2000ms了?) (14.8.7更,将getnum换成scanf就能ac,这是啥节奏??????????????????????????????????数据有问题啊喂??

明天再来看看吧。。估计写挫了。

本题先用floyd跑完点之间的最短路,设状态f[i][j]表示访问情况为i的时候现在所在的点为j的最小值,有

f[i][j]=min(f[i-bit(j)][k]+d[k][j], f[i][k]+d[k][j]),其中bit(j)表示j的位置的二进制表示,d[k][j]表示k到j的最短路

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define read(a) a=getnum()
#define print(a) printf("%d", a)
#define bit(x) (1<<x)
inline int getnum() { int ret=0; char c; int k=1; for(c=getchar(); c<'0' || c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0' && c<='9'; c=getchar()) ret=ret*10+c-'0'; return k*ret; }

const int N=17;
int f[1<<N][N], d[N][N], all, n;

int main() {
	read(n); ++n;
	CC(f, 0x3f); all=bit(n)-1;
	rep(i, n) rep(j, n) read(d[i][j]);
	rep(k, n) rep(i, n) rep(j, n) d[i][j]=min(d[i][j], d[i][k]+d[k][j]);
	f[0][0]=0;
	for1(i, 0, all) for2(now, 0, n) for2(from, 0, n) if(i&bit(now))
		f[i][now]=min(f[i][now], min(f[i-bit(now)][from]+d[from][now], f[i][from]+d[from][now]));
	print(f[all][0]);
	return 0;
}

 

 


 

 

题目描述 Description

有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上。n个不同的客户分别在1~n个编号的城市中。送外卖的 从0号城市出发,然后n个城市都要走一次(一个城市可以走多次),最后还要回到0点(他的单位),请问最短时间是多少。现在已知任意两个城市的直接通路的 时间。

输入描述 Input Description

第一行一个正整数n (1<=n<=15)

接下来是一个(n+1)*(n+1)的矩阵,矩阵中的数均为不超过10000的正整数。矩阵的i行j列表示第i-1号城市和j-1号城市之间直接通路的时间。当然城市a到城市b的直接通路时间和城市b到城市a的直接通路时间不一定相同,也就是说道路都是单向的。

输出描述 Output Description

一个正整数表示最少花费的时间

样例输入 Sample Input

3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0

样例输出 Sample Output

8

数据范围及提示 Data Size & Hint

1<=n<=15

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值