
2 4 5 2 1 2 8 2 3 4 3 4 19 4 1 6 2 4 7 2 25 18 1 3 4 12 6 1 3 4 6 2 1 2 5 1 4 4 3 1 1 3 2 1 3 4 1 2 4 10 2 8 3 1 4 4 8 3 1 2
Case #1: 53 Case #2: 14
题意:给定一个带权无向图(n<=50)和图中若干个景点(k<=8)(每个顶点可包含多个景点),..现在要你‘游’这些景点,‘游’过这些景点的条件是你在这个点等上了一定的时间,如果你有fastpass,也就是经过某些点,那么只需要等FT的时间,否则要等T的时间,问从1号点出发完成任务再回到1号点的最少时间。
下面是看了别的人解题报告:
思路,状态压缩dp,f[i][mark][j]表示当前在j这个点,已经‘游’过的点的2进制状态为i,手上有fastpass的2进制为mark的最少时间
则f[i][mark][j] ==> f[i | (1<<p)][new_mark][loc[p]] // p是下一个要去的景点号,loc[p]是他的位置,new_mark是经过loc[p]后新的关于fastpass的2进制状态
同理f[i]mark][j][ => f[i][new_mark][j‘] // 往另外一个点走,不是最‘游’那些点,可以认为有意图地去是拿fastpass。如果mark==new_mark, 这个式子有没有都不影响结果。
#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
const int N =55;
const int inf = 999999999;
#define mov(a) (1<<(a))
int mapt[N][N],dp[1<<9][1<<9][N],n
int P[N],T[N],FT[N],pass[N],k;
void init()
{
for(int j=0; j<mov(k); j++)
for(int e=0; e<mov(k); e++)
for(int i=0; i<=n; i++)
dp[j][e][i]=inf;
for(int i=0; i<=n; i++)
{
pass[i]=0;
for(int j=0; j<=n; j++)
mapt[i][j]=inf;
mapt[i][i]=0;
}
}
void floyd()
{
for(int e=1; e<=n; e++)
for(int i=1; i<=n; i++)
if(e!=i)
{
for(int j=1; j<=n; j++)
if(i!=j&&e!=j&&mapt[i][j]>mapt[i][e]+mapt[e][j])
mapt[i][j]=mapt[i][e]+mapt[e][j];
}
}
int DP()
{
dp[0][0][1]=0;
for(int sta=0; sta<mov(k); sta++)
for(int spa=0; spa<mov(k); spa++)
for(int i=1; i<=n; i++)
if(dp[sta][spa][i]!=inf)
{
for(int e=0; e<k; e++)
if((sta&mov(e))==0)
{
int cost=((spa|pass[P[e]])&mov(e))>0?FT[e]:T[e];
if(dp[sta|mov(e)][spa|pass[P[e]]][P[e]]>dp[sta][spa][i]+mapt[i][P[e]]+cost)
dp[sta|mov(e)][spa|pass[P[e]]][P[e]]=dp[sta][spa][i]+mapt[i][P[e]]+cost;
}
//去找旅游景点卷
for(int j=1; j<=n; j++)
if(pass[j]>0&&dp[sta][spa|pass[j]][j]>dp[sta][spa][i]+mapt[i][j])
dp[sta][spa|pass[j]][j]=dp[sta][spa][i]+mapt[i][j];
}
//找答案
int ans=inf;
for(int spa=0; spa<mov(k); spa++)
for(int i=1;i<=n;i++)
if(ans>dp[mov(k)-1][spa][i]+mapt[i][1])
ans=dp[mov(k)-1][spa][i]+mapt[i][1];
return ans;
}
int main()
{
int t,cas=0,m,a,b,c;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
init();
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
if(mapt[a][b]>c)
mapt[a][b]=mapt[b][a]=c;
}
for(int i=0;i<k;i++)
{
scanf("%d%d%d%d",&P[i],&T[i],&FT[i],&m);
while(m--)
{
scanf("%d",&a);
pass[a]|=1<<i;
}
}
floyd();
printf("Case #%d: %d\n",++cas,DP());
}
}
HDU4114 Disney's FastPass(floyd+状态压缩DP)旅游问题升级(难)
原文:http://blog.csdn.net/u010372095/article/details/45080965