zoukankan      html  css  js  c++  java
  • 【NOIP2014模拟11.1B组】蜀传之单刀赴会

    论坛中我的总结:
    这题用状压DP实现。
    我们先对于起点和终点,以及朋友家每个跑一遍spfa,将这些点定义为关键点,两两之间都求出了最短路,然后我们可以用状压DP来解决问题。
    我们可以设f[i][j]表示当前到达点i,走过朋友家的状态为j的最短路。这是从1到n的!
    然后我们再设g[i][j]表示当前到达点j,走过朋友家的状态为j的最短路。这是从n到1的!
    而f的初始值为:f[0][0]=0;(0表示起点,k+1表示终点)
    g的初始值为:g[k+1]=f[k+1];
    最后的答案在g[0]中找即可。

    这题就是个状压DP,我们设:

    f[i][j]表示当前在第i个朋友家,走到过的状态为j的最小时间。

    这是从1走到n的!!!

    再设g[i][j]表示当前在第i个朋友家,都到过的状态为j的最小时间。

    这是从n返回1的!!!

    做完f后就把f[k]赋值为g[k],然后在照做一遍就可以了。
    我们可以将第0个朋友表示为1,第k+1个朋友表示为n。
    上标:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 10010
    #define M 50010
    #define ll long long
    using namespace std;
    struct node{int v,fr,l;}e[M<<2];
    int n,m,K,t,tail[N],cnt=0,F[N<<3],fd[17],x,ans=0;
    ll d[N],dis[17][17],f[17][70010],g[17][70010],time;
    bool bz[N];
    
    inline int read()
    {
    	int x=0; char c=getchar();
    	while (c<'0' || c>'9') c=getchar();
    	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x;
    }
    
    inline void add(int u,int v,int l) {e[++cnt]=(node){v,tail[u],l}; tail[u]=cnt;}
    
    void spfa(int x)
    {
    	memset(d,60,sizeof(d));
    	int l=0,r=1;F[1]=x;d[x]=0;
    	while (l++<r)
    	{
    		for (int p=tail[F[l]],v;p;p=e[p].fr)
    		{
    			if (d[F[l]]+e[p].l>=d[v=e[p].v]) continue;
    			d[v]=d[F[l]]+e[p].l;
    			if (!bz[v]) bz[v]=1,F[++r]=v;
    		}
    		bz[F[l]]=0;
    	}
    }
    
    int change(int x)
    {
    	int s=0;
    	while (x>0) s+=(x & 1),x>>=1;
    	return s;
    }
    
    int main()
    {
    	freopen("shu.in","r",stdin);
    	freopen("shu.out","w",stdout);
    	n=read(),m=read(),K=read(),t=read();
    	for (int i=1,u,v,l;i<=m;i++)
    	{
    		u=read(),v=read(),l=read();
    		add(u,v,l),add(v,u,l);
    	}
    	for (int i=1;i<=K;i++) fd[i]=read();
    	fd[0]=1;fd[++K]=n;
    	for (int i=0;i<=K;i++)
    	{
    		spfa(fd[i]);
    		for (int j=0;j<=K;j++)
    			dis[i][j]=(i==j) ? 0:d[fd[j]];
    	}
    	/*
    	for (int i=0;i<=K;i++)
    	{
    		for (int j=0;j<=K;j++)
    			printf("%d ",dis[i][j]);
    		puts("");
    	}
    	*/
    	memset(f,60,sizeof(f));f[0][0]=0;
    	for (int j=0;j<=(1<<K)-1;j++)
    		for (int i=0;i<=K;i++)
    		{
    			if (f[i][j]>t) continue;
    			for (int k=1;k<=K;k++)
    			{
    				x=j | (1<<k-1);
    				f[k][x]=min(f[k][x],f[i][j]+dis[i][k]);
    			}
    		}
    	memset(g,60,sizeof(g));
    	for (int i=0;i<=(1<<K)-1;i++)
    		g[K][i]=f[K][i];
    	for (int j=0;j<=(1<<K)-1;j++)
    		for (int i=K;i>=0;i--)
    		{
    			if (g[i][j]>t) continue;
    			for (int k=0;k<=K;k++)
    			{
    				if (!k) x=j;
    				else x=j | (1<<k-1);
    				g[k][x]=min(g[k][x],g[i][j]+dis[i][k]);
    			}
    		}
    	for (int i=0;i<=(1<<K)-1;i++)
    		if (g[0][i]<=t)
    		{
    			x=change(i);
    			if (ans>x) continue;
    			if (ans<x) ans=x,time=g[0][i];
    			if (time>g[0][i]) time=g[0][i];
    		}
    	if (ans==0) puts("-1");
    	else printf("%d %lld
    ",ans-1,time);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    JavaScript
    CSS
    HTML5&CSS
    I2C mux和复杂拓扑
    如何实例化I2C设备
    SMBus 协议
    I2C 协议
    I2C和SMBus简介
    ubuntu20.04系统下更新Raspberry Pi4的DTB
    通过configfs配置的Linux USB gadget
  • 原文地址:https://www.cnblogs.com/jz929/p/11817584.html
Copyright © 2011-2022 走看看