[JSOI2010]快递服务

I.[JSOI2010]快递服务

我们约定共有n个地点,依次登记了m家公司。

思路1.

f[l][i][j][k]表示:当前某一个司机在第i家公司(注意是公司!1000家那个!),第二个司机在第j家,第三个司机在第k家,当前我们遍历到了第l家公司。依次转移即可。

复杂度O(m4)

思路2.观察到i,j,k中必有一个等于l(不然你位置l的货是哪辆车发的?),因此我们可以省掉一维。设f[i][j][k]即可。

复杂度O(m3)

明显第一维可以滚动掉,因此空间复杂度便可以通过。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,dis[210][210],f[2][1010][1010],pos[1010],m,res=0x3f3f3f3f;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&dis[i][j]);
	memset(f,0x3f3f3f3f,sizeof(f)),f[1][2][1]=0;
	pos[++m]=1,pos[++m]=2,pos[++m]=3;
	while(scanf("%d",&pos[++m])!=EOF);
	for(int i=3;i<m;i++){
		for(int j=1;j<=i;j++)for(int k=1;k<j;k++)f[!(i&1)][j][k]=0x3f3f3f3f;
		for(int j=1;j<i;j++)for(int k=1;k<j;k++){
			f[!(i&1)][j][k]=min(f[!(i&1)][j][k],f[i&1][j][k]+dis[pos[i]][pos[i+1]]);
			f[!(i&1)][i][k]=min(f[!(i&1)][i][k],f[i&1][j][k]+dis[pos[j]][pos[i+1]]);
			f[!(i&1)][i][j]=min(f[!(i&1)][i][j],f[i&1][j][k]+dis[pos[k]][pos[i+1]]);
		}
//		for(int j=1;j<=i;j++){for(int k=1;k<j;k++)printf("%d ",f[!(i&1)][j][k]);puts("");}puts("");
	}
	for(int j=1;j<m;j++)for(int k=1;k<j;k++)res=min(res,f[m&1][j][k]);
	printf("%d\n",res);
	return 0;
} 

思路3.发现O(m3)只能拿到50%。似乎只有最后两维可以优化成n2的。

我们设f[i][j][k]表示:当前某一辆车在第i公司(还是1000家那个!)剩下两辆车分别在第j和第k收件地点(是200家那个!)。

复杂度为O(mn2)

这是正解尽管出题人丧心病狂卡长只有70%但是开个O3然后卡卡长就过了

代码:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
int n,dis[210][210],f[2][1010][1010],pos[1010],m,res=0x3f3f3f3f;
inline void read(int &x){
	x=0;
	register char c=getchar();
	while(c>'9'||c<'0')c=getchar();
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
inline void print(int x){
	if(x<=9)putchar('0'+x);
	else print(x/10),putchar('0'+x%10);
}
int main(){
	read(n);
	for(register int i=1;i<=n;i++)for(register int j=1;j<=n;j++)read(dis[i][j]);
	memset(f,0x3f3f3f3f,sizeof(f)),f[1][2][1]=0;
	pos[++m]=1,pos[++m]=2,pos[++m]=3;
	while(scanf("%d",&pos[++m])!=EOF);
	for(register int i=3;i<m;i++){
		for(register int j=1;j<=n;j++)for(register int k=1;k<=n;k++)f[!(i&1)][j][k]=0x3f3f3f3f;
		for(register int j=1;j<=n;j++)for(register int k=1;k<=n;k++){
			f[!(i&1)][j][k]=min(f[!(i&1)][j][k],f[i&1][j][k]+dis[pos[i]][pos[i+1]]);
			f[!(i&1)][pos[i]][k]=min(f[!(i&1)][pos[i]][k],f[i&1][j][k]+dis[j][pos[i+1]]);
			f[!(i&1)][pos[i]][j]=min(f[!(i&1)][pos[i]][j],f[i&1][j][k]+dis[k][pos[i+1]]);
		}
//		for(int j=1;j<=i;j++){for(int k=1;k<j;k++)printf("%d ",f[!(i&1)][j][k]);puts("");}puts("");
	}
	for(register int j=1;j<=n;j++)for(register int k=1;k<=n;k++)res=min(res,f[m&1][j][k]);
	print(res);
	return 0;
} 
posted @   Troverld  阅读(46)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示