hdu 4640 Island and study-sister(状态压缩dp)

先处理前两个学长到达各个点所需要的最少时间,在计算前两个学长和最后一个学长救出所有学妹的最少时间。

 

#include<stdio.h>

#include<string.h>

#include<vector>

#include<algorithm>

using namespace std;

const int inf=1000000000;

struct node{

	int b,d;

};

struct node2{

    int dst,sta;

    node2(){}

    node2(int _dst,int _sta)

    {

        dst=_dst;sta=_sta;

    }

}q[3000000];

int dp[17][1<<17],n;

int f[17],dis[1<<17],dis2[1<<17],s;

vector<node>mp[17];

void bfs()//建立所有状态

{

    int i,j,k,st=0,ed=0,sta,dst,tmp;

    node2 p;

    node u;

    p.dst=1;p.sta=1;

    dp[1][1]=0;

    q[ed++]=p;

    while(st<ed)

    {

        p=q[st];

        dst=p.dst;

        sta=p.sta;

        for(i=0;i<mp[dst].size();i++)

        {

            u=mp[dst][i];tmp=sta|f[u.b];



            if(dp[u.b][tmp]>dp[dst][sta]+u.d)

            {



                dp[u.b][tmp]=dp[dst][sta]+u.d;

                q[ed++]=node2(u.b,tmp);

            }

        }

        st++;

    }

}

int main()

{

	int t,i,j,m,k,a,b,d,h,iter,juli,v=1,x;

	f[1]=1;

	for(i=2;i<=17;i++)f[i]=f[i-1]<<1;

	node p;

	scanf("%d",&t);

	while(t--)

	{

		scanf("%d%d",&n,&m);

		for(i=1;i<=n;i++)mp[i].clear();

		for(i=1;i<=n;i++)

        for(j=0;j<1<<n;j++)

           dp[i][j]=inf;

		while(m--)

		{

			scanf("%d%d%d",&a,&b,&d);

			p.b=b;p.d=d;

			mp[a].push_back(p);

			p.b=a;

			mp[b].push_back(p);

		}

		bfs();

		for(i=1;i<1<<n;i+=2){//求出所有状态的最短时间

			dis[i]=inf;

		    for(j=1;j<=n;j++)

		    	if(dp[j][i]<dis[i])

		    		dis[i]=dp[j][i];

		}

		scanf("%d",&k);

		int tmp=0;

		for(i=0;i<k;i++)//目标状态

        {

            scanf("%d",&s);

            tmp|=f[s];

        }

        printf("Case %d: ",v++);

        int ans=inf;

        for(i=0;i<1<<n;i++)dis2[i]=inf;//两个学长一起

        for(i=0;i<1<<n;i++)

        for(h=j=i^((1<<n)-1);;j=h&(j-1)){

            if(dis2[i|j|1]>(x=max(dis[i|1],dis[j|1])))

                dis2[i|j|1]=x;

            if(j==0)break;

        }

        for(i=0;i<1<<n;i++)//三个一起

        for(h=j=i^((1<<n)-1);;j=h&(j-1)){

            if(( ( (i|j|1)&tmp  )==tmp) && ans>(x=max(dis[i|1],dis2[j|1])))

                ans=x;

            if(j==0)break;

        }

        if(ans==inf)ans=-1;

        printf("%d\n",ans);

	}

	return 0;

}


 

 

你可能感兴趣的:(HDU)