abc F 求调
  • 板块学术版
  • 楼主fcy20180201
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/3/9 22:49
  • 上次更新2024/3/10 09:30:48
查看原帖
abc F 求调
866154
fcy20180201楼主2024/3/9 22:49

思路是枚举攒够后面需要的所有钱的点。然后前面的点都是只要钱够就走,钱不够就等。再用 DP 算出每个点走到 (N,N)(N,N) 最少需要花的钱,以此得出需要攒多少钱才能直接走完。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int n;
ll p[85][85],r[85][85],d[85][85],dp1[85][85],rest[85][85],dp2[85][85],ans=1e18;
int main(){
	scanf("%d",&n);
	for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)p[i][j]=1;
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%lld",&p[i][j]);
	for(int i=1;i<=n;i++)for(int j=1;j<n;j++)scanf("%lld",&r[i][j]);
	for(int i=1;i<n;i++)for(int j=1;j<=n;j++)scanf("%lld",&d[i][j]);
	memset(dp1,0x3f,sizeof(dp1)); 
	dp1[1][1]=0;
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){
		if(i==1 && j==1)continue;
		ll x=dp1[i][j-1]+(max(0ll,r[i][j-1]-rest[i][j-1])+p[i][j-1]-1)/p[i][j-1];
		ll y=dp1[i-1][j]+(max(0ll,d[i-1][j]-rest[i-1][j])+p[i-1][j]-1)/p[i-1][j];
		ll rx=(max(0ll,r[i][j-1]-rest[i][j-1])+p[i][j-1]-1)/p[i][j-1]*p[i][j-1]-r[i][j-1]+rest[i][j-1];
		ll ry=(max(0ll,d[i-1][j]-rest[i-1][j])+p[i-1][j]-1)/p[i-1][j]*p[i-1][j]-d[i-1][j]+rest[i-1][j];
		dp1[i][j]=min(x,y)+1;
		if(x<y)rest[i][j]=rx;
		if(x>y)rest[i][j]=ry;
		if(x==y)rest[i][j]=max(rx,ry);
	} 
	memset(dp2,0x3f,sizeof(dp2));
	dp2[n][n]=0;
	for(int i=n;i;i--)for(int j=n;j;j--){
		if(i==n && j==n)continue;
		dp2[i][j]=min(dp2[i+1][j]+d[i][j],dp2[i][j+1]+r[i][j]);
	}
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
		ans=min(ans,dp1[i][j]+(max(0ll,dp2[i][j]-rest[i][j])+p[i][j]-1)/p[i][j]+(n-i)+(n-j));
	printf("%lld",ans);
	return 0;
}
2024/3/9 22:49
加载中...