题目描述(POJ3311):
披萨店以尽可能快地向顾客提供披萨而自豪。司机将等待一个或多个(最多10个)订单被处理,然后开始送 货。他愿意走最短的路线运送这些货物,然后返回比萨店,即使这意味着途中要经过相同的地点或披萨店不止一次。
输入: 输入包含多个测试用例。每个测试用例的第1行都包含一个整数n (1≤n ≤10),表示要交付的订单数量。之后n +1行中的每一行都包含n +1个整数,表示披萨店(编号0)和n 个位置(编号为1~n)之间的行程时间。第i 行上的第j 个值表示从位置i 直接到位置j 的时间,时间值可能不对称,即从位置i 直接到位置j 的时间可能与从位置j 直接到位置i 的时间不同。n =0时将终止输入。
输出: 对每个测试用例,都单行输出交付所有披萨并返回披萨店的最短时间。
#include<iostream>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
int g[11][11],dp[1<<10][11],n;
void floyd()//弗洛伊德求最短路
{
for (int k=0;k<n;k++)
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
void Traveling()//递推求dp[s][u]
{
memset(dp,0x3f,sizeof(dp));
dp[(1<<n)-1][0]=0;
for (int s=(1<<n)-2;s>=0;s--)
for (int u=0;u<n;u++)
for (int v=0;v<n;v++)
{
if (!(s>>u&1)&&u!=0) continue;
if (!(s>>v&1)&&dp[s][u]>dp[s|1<<v][v]+g[u][v])
dp[s][u]=dp[s|1<<v][v]+g[u][v];
}
}
int main()
{
while (1)
{
cin>>n;
if (!n) break;
n++;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
cin>>g[i][j];
floyd();
Traveling();
cout<<dp[0][0]<<endl;
}
return 0;
}
用的状压DP,一直RE,有时还会莫名奇妙的CE