• 「美团 CodeM 初赛 Round B」送外卖2


    思路:
    题目要求最多能送多少个外卖,不妨转换思路,求怎么在相同的送外卖情况下花最少的时间。
    这种解法不仅便于设计程序,而且正确性显然:求出这个状态的最小时间,就越有可能转移到能取最优值的那个状态上面。

    于是使用利于理解的记忆化dfs,记录当前点是哪个,各包裹的状态(0/1/2,0表示没动,1表示拿在手上,2表示送完),然后再图上乱走,只要能标1就标1,标了1以后才能标2。在这个求到达各状态的min时间的同时记录最大的送外卖数。

    难点还是在状态和转移的设计上。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=21;
    int n,m,q;
    int f[N][59050*3];
    int bin[11];
    int g[N][N];
    int s[N],t[N],l[N],r[N];
    int ans,xx; 
    int get (int x)
    {
    	int tt=0;
    	for (int u=10;u>=0;u--){
    		if (x>=bin[u]*2) tt++;
    		while (x>=bin[u]) x-=bin[u];
    	}
    	return tt;
    }
    int check (int x,int y)//x的第y位是0,1,2中的哪一个{
    	for (int u=10;u>y;u--)
    		while (x>=bin[u]) 
    			x=x-bin[u];
    	if (x>=bin[y]*2) return 2;
    	if (x>=bin[y]) return 1;
    	return 0;
    } 
    void dfs (int now,int x,int z)//现在在哪一个点,物品的状态,现在的时间 
    { 
    	for (int u=1;u<=q;u++){
    		if (s[u]==now&&check(x,u)==0&&z>=l[u])//这里可取
    			x=x+bin[u];
    	}
            for (int u=1;u<=q;u++){
    		if (t[u]==now&&check(x,u)==1&&z<=r[u])//这里可放
    			x=x+bin[u];
    	}
    	if (f[now][x]<=z) return ;
    	f[now][x]=z; 
    	ans=max(ans,get(x));
    
    
    	if (z>=xx) return ;
    	for (int u=1;u<=q;u++)
    	{ 
      	        if (check(x,u)==0)  dfs(s[u],x,max(z+g[now][s[u]],l[u]));//速速去取
    		if (check(x,u)==1) dfs(t[u],x,z+g[now][t[u]]);//速速去放
    	}
    
    
    }
    
    
    int main(){
    	bin[0]=1;
        for(int u=1;u<=10;u++)
           bin[u]=bin[u-1]*3; 
    	
        memset(f,127,sizeof(f));
    	memset(g,63,sizeof(g));
    	
        scanf("%d%d%d",&n,&m,&q);
    
    	for (int u=1;u<=n;u++) g[u][u]=0;
    	
        for (int u=1;u<=m;u++){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		g[x][y]=min(g[x][y],z);
    	}
    	for (int k=1;k<=n;k++)//求最短路,k循环在最外层
    		for (int u=1;u<=n;u++)
    			for (int i=1;i<=n;i++)
    				g[u][i]=min(g[u][i],g[u][k]+g[k][i]);
    
    
    	for (int u=1;u<=q;u++){
    		scanf("%d%d%d%d",&s[u],&t[u],&l[u],&r[u]);
    		xx=max(xx,r[u]);
    	}
    
    	dfs(1,0,0);
    	printf("%d\n",ans);
    
    	return 0;
    }
    
  • 相关阅读:
    在Springboot 中使用 flyway
    Ryu 学习资料总结
    OpenDaylight 学习资料整理
    在 Ubuntu16.04 上安装 etcd
    ovs 连接 Floodlight 控制器
    etcd 学习资料整理
    Floodlight 学习资料整理
    算法用例
    数据库
    他山之石
  • 原文地址:https://www.cnblogs.com/GUOGaby/p/15788929.html
Copyright © 2020-2023  润新知