#6177. 「美团 CodeM 初赛 Round B」送外卖2

这题很容易想到状压的记忆化搜索

f[i][j][k]表示到第i个点    拿物品的状态    送到物品的状态

然后就可以愉快地dfs了

结果MLE。。

1024*1024*20爆了

那怎么办。。。。。

反正对于一种物品只有三种状态

那不如使用三进制状压。。。。

算了一下空间复杂度过得去

于是就A了

一开始还因为误以为双向边WA了几发。。

#include<cstdio>
#include<cstdlib>
#include<cstring>
const int N=21;
int n,m,q;
int g[N][N];
int s[N],t[N],l[N],r[N];
int f[N][59050*3];
int bin[11];
int ans=0;
int mymax (int x,int y){return x>y?x:y;}
int mymin (int x,int y){return x<y?x:y;}
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位是什么
{
//	printf("%d %d\n",x,y);
	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;
}
int xx=0;
void dfs (int now,int x,int z)//现在在哪一个点    物品的状态    现在过了多少时间 
{
/*	printf("%d %d\n",now,z);
	system("pause");*/
	for (int u=1;u<=q;u++)
	{
		if (s[u]==now&&check(x,u)==0&&z>=l[u])//这里可以取
			x=x+bin[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=mymax(ans,get(x));
	if (z>=xx) return ;
	if (ans>=q) return ;
	for (int u=1;u<=q;u++)
	{
		if (z+g[now][t[u]]>r[u]) continue;
		if (check(x,u)==0)	dfs(s[u],x,mymax(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;
//	printf("%d\n",bin[10]);
	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]=mymin(g[x][y],z);
	}
	for (int k=1;k<=n;k++)
		for (int u=1;u<=n;u++)
			for (int i=1;i<=n;i++)
				g[u][i]=mymin(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=mymax(xx,r[u]);
	}
	dfs(1,0,0);
	printf("%d\n",ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值