Hie with the Pie 动态规划的模板题

Hie with the Pie

Problem Description
The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately,
due to cutbacks, they can afford to hire only one driver to do the deliveries. He will wait for 1 or more
(up to 10) orders to be processed before he starts any deliveries. Needless to say, he would like to take
the shortest route in delivering these goodies and returning to the pizzeria, even if it means passing
the same location(s) or the pizzeria more than once on the way. He has commissioned you to write a
program to help him.
Input
Input will consist of multiple test cases. The first line will contain a single integer n indicating the
number of orders to deliver, where 1 ≤ n ≤ 10. After this will be n + 1 lines each containing n + 1
integers indicating the times to travel between the pizzeria (numbered 0) and the n locations (numbers
1 to n). The j-th value on the i-th line indicates the time to go directly from location i to location j
without visiting any other locations along the way. Note that there may be quicker ways to go from i
to j via other locations, due to different speed limits, traffic lights, etc. Also, the time values may not
be symmetric, i.e., the time to go directly from location i to j may not be the same as the time to go
directly from location j to i. An input value of n = 0 will terminate input.
Output
For each test case, you should output a single number indicating the minimum time to deliver all of
the pizzas and return to the pizzeria.
Sample Input
3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0
Sample Output
8

请允许我对它进行一个简陋的翻译。

比萨,一起奔跑

Problem Description
Pizazz Pizzeria 有一件令他十分骄傲的事情,他能够很快地向客户派送比萨。不幸的是,由于裁员,他们只能雇佣一个司机来送货。他会等待若干(一个到十个)订单,之后开始派送比萨。毫无疑问,他希望通过最短的路线来运送这些货物,并返回 pizzeria ,即便是通过任何同一地点不止一次。他委托你写一个程序来帮助他。
Input
输入将包括多个测试案例。
第一行将包括一个整数 n 表示派送订单的数量,并且保证1≤n≤10.
之后将会有 n+1 行,每一行都有 n+1 个整数表示在 pizerria ( 0 号地点)和 n 个地点(1~n号地点)之间旅行所消耗的距离。
第 i 行里第 j 个数表示从 i 号地点到 j 号地点所消耗的时间,并且,没有中途不会到达其他任何地点。
注意:由于限速、红绿灯等多种因素影响,可能存在其他路线可以更快的从 i 号地点到达 j 号地点。
并且,时间消耗并不一定是对称的。换句话说,从 i 号地点到 j 号地点的时间与从 j 号地点到 i 号地点的时间不一定一样。
最后,当 n 为 0 时,说明输出终止。
Output
对于每一个测试样例,你只需输出一个数字,表示派发所有比萨后,回到比萨店的最小时间。
Sample Input
3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0
Sample Output
8

观察题目,我们可以很好地理解题目意思,从 0 号位置出发,将每一个位置都至少拜访一遍,最后回到 0 号位置所要的最小代价。
对于这道题目,我们有多种选择,例如,我们可以直接选择使用深度优先搜索,甚至加上贪心策略,并配合 Floyd Shortest Path Algorithm 解决本题。
当然,在此我们可以选择使用动态规划的方法解决问题,在此,是状态压缩动态规划处理。
那么,我们就很容易想到,对于 f[i][j],表示人物在 i 号位置,并且遍历状态为 j 的情况,所需要的最小代价。
那么,对于 f[0][?] 使 ? 为遍历所有地点的状态,则其 f[0][?] 便是正确答案。
通过位运算的处理,我们可以进行状态压缩。
将一个整数二进制观察,每一位当做一个地点的状态,注意,只有两种状态,被遍历过或者没有被经过。
就例如这样,111(7) 表示 1、2、3 号地点都被遍历过, 1010(10) 表示 2、4 号地点都被遍历过。
那么,我们就可以在 210 左右的时间里,将所有遍历情况确定下来。
然后进行递推表达就可以了。
当然,状态转移还是有值得提醒的地方,为了更快地进行状态的转移,我们可以将不同的状态预处理,将其归类,使得我们的状态枚举有一定的阶段性,便于我们减少程序的复杂度。
同时,正如上面所述,运用 Floyd Shortest Path Algorithm 可以有效的帮助我们进行后续的相同遍历状态转移,便于我们计算答案。也许这样会出现错误的状态转移,但是,我们可以肯定的是,错误的状态转移一定没有正确的状态转移优,所以,我们可以将其忽略。
最后,代码如下。

#include 
#include 
#include 

using namespace std;

int n;
int dist[11][11];
int f[11][1024];
int tot[11];
int q[11][1024];

int getpoint(int x)
{
	int o=(x&1)?1:0;
	while (x>>=1)
		if (x&1)
			o++;
	return o;
}

int main()
{
	while (scanf("%d",&n),n)
	{
		memset(tot,0,sizeof(tot));
		for (register int i=1;i<(1<

你可能感兴趣的:(Hie with the Pie 动态规划的模板题)