AtCoder Beginner Contest 320 F Fuel Round Trip

ABC 320 F

题意

汽车从0开始出发,最终到达Xn再返程回到0,一开始有汽油H升,每公里耗油一升,在点Xi有加油站,每个加油站只可以加油一次,并且一次就加Wi升,花费Pi,且最大油量有限制H。问最小花费

思路

它的数据范围n,H300,暴力dp,设状态dpi,j,k为在站点i出发时油量为j,返程回到站点i时油量为k,可以滚动优化掉一维,时间复杂度为O(nH2)

状态转移方程

假设停在点i,有两种决策,在该点加油或不加
不加的话为

dpi+1,jdis,k+dis=dpi,j,k

去的时候,加油为

dpi+1,jdis+Wi,k+dis=dpi,j,k+Pi

回来的时候,加油为

dpi+1,jdis,k+disWi=dpi,j,k+Pi

其中disxi+1xi,注意状态的合法范围,隐藏条件为disiHkHdis,想一下为什么

代码

void solve() 
{
	cin>>n>>h;
	for(int i=0;i<n;i++) 
	{
		cin>>x[i];
	}
	for(int i=0;i<n-1;i++) cin>>p[i]>>f[i];
	
	dp[h][0]=0;
	
	for(int it=0;it<n-1;it++) 
	{
		int dis = x[it]-(it==0?0:x[it-1]);
		memset(new_dp,0x3f,sizeof(new_dp));
		for(int i=0;i<=h;i++) 
		{
			for(int j=0;j<=h;j++) 
			{
				if(dp[i][j]==inf) continue;
				int ni=i-dis,nj=j+dis;
				if(ni>=0&&nj<=h) 
				{
					new_dp[ni][nj] = min(new_dp[ni][nj],dp[i][j]);
					new_dp[min(ni+f[it],h)][nj] = min(new_dp[min(ni+f[it],h)][nj],dp[i][j]+p[it]);
					new_dp[ni][max(nj-f[it],0ll)] = min(new_dp[ni][max(nj-f[it],0ll)],dp[i][j]+p[it]);
				}
			}
		}
		swap(dp,new_dp);
	}
	
	int dis = (x[n-1]-(n==1?0:x[n-2]))*2;
	
	int ans=inf;
	
	for(int i=0;i<=h;i++) 
	{
		for(int j=0;j<=h;j++) 
		{
			if(dp[i][j]==inf) continue;
			if(i-dis>=j) ans=min(ans,dp[i][j]);
		}
	}
	
	cout<<(ans==inf?-1:ans)<<endl;
} 
posted @   Liang2003  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示