hdu 5418(状态压缩dp+Floyd)

点击打开链接


解题思路:这道题目和TSP问题很相似,唯一不同的是同一个点可以重复走几次。。。。

这道题目只有16个顶点,所以很容易想到状态压缩dp,dp[i][j]表示到达顶点i时的状态为j的最小花费,那么状态方程也很容易推理出来dp[i][j] = min(dp[k][j-1<<i]+map[i][k]);这里注意,由于每一个点可以到达多次,所以这里的map要先用Floyd算法来处理,否则就会出现用还未更新的状态去更新当前的状态,这样很明显两个状态都无法保证是最优的,第一次WA就是卡在这里,后面看了别人的解题报告,才明白了Floyd算法在这里的重要性。。。


AC:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int inf = 0x3f3f3f3f;
int n,m;
int dp[20][1<<17],map[20][20];

int main()
{	
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int w,u,v,bit;
		scanf("%d%d",&n,&m);
		memset(map,inf,sizeof(map));
		memset(dp,inf,sizeof(dp));
		for(int i = 1; i <= m; i++)
		{
			scanf("%d%d%d",&u,&v,&w);
			map[u][v] = min(map[u][v],w);
			map[v][u] = map[u][v];
		}
		for(int k = 1; k <= n; k++)
			for(int i = 1; i <= n; i++)
				for(int j = 1; j <= n; j++)
					map[i][j] = min(map[i][j],map[i][k] + map[k][j]);
		bit = 1<<n;
		dp[1][1] = 0;
		for(int j = 1; j < bit; j++)
			for(int k = 1; k <= n; k++)
				for(int i = 1; i <= n; i++)
				{
					if(map[i][k] == inf) continue;
					int tmp = 1 << (i-1);
					if(j & tmp)
					{
						if(dp[k][j] != inf)
						{
							dp[i][j] = min(dp[i][j],dp[k][j] + map[i][k]);
						}
						if(dp[k][j-tmp] != inf)
						{
							dp[i][j] = min(dp[i][j],dp[k][j-tmp] + map[i][k]);
						}
					}
				}
		printf("%d\n",dp[1][bit-1]);
	}
	return 0;
}


你可能感兴趣的:(dp)