玄关,蒟蒻求条 DP,带注释
查看原帖
玄关,蒟蒻求条 DP,带注释
1251532
apiad楼主2024/3/11 19:36
// Author: gsczl71
// Copyright (c) 2024 gsczl71 All rights reserved.
// Problem: F - Earn to Advance
// Contest: AtCoder - 	Toyota Programming Contest 2024#3(AtCoder Beginner Contest 344)
// URL: https://atcoder.jp/contests/abc344/tasks/abc344_f
// Memory Limit: 1024 MB
// Time Limit: 4000 ms

#include<bits/stdc++.h>
#define ll long long
#define i128 __int128
#define ull unsigned long long
#define pii pair<int,int>
#define pll pair<long long, long long>
#define fs first
#define sc second
#define endl '\n'
#define debug puts("AK IOI")
#define re register
#define pb push_back
#define mem(a,x) memset((a),(x),sizeof(a))
#define vi vector<int>
#define pq priority_queue
using namespace std;
#define int long long
const int mod = 1e9+7;
//const int mod = 998244353;
const int inf = 0x3f3f3f3f,N = 83,M = 1e6+5,K = 3000+5;
int linf = 0x3f3f3f3f3f3f3f3f;
map<int,pii> dp[N][N];
int p[N][N];
int d[N][N];
int r[N][N];
int n;
void solve(){
	cin >> n;
	for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) cin >> p[i][j];
	for(int i = 1;i <= n;i++) for(int j = 1;j <= n - 1;j++) cin >> r[i][j];
	for(int i = 1;i <= n-1;i++) for(int j = 1;j <= n;j++) cin >> d[i][j];
	
	dp[0][1][0] = dp[1][0][0] = {0,1}; 
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= n;j++)
			for(int pi = 1;pi <= i;pi++)
				for(int pj = 1; pj <= j;pj++)
					dp[i][j][max(p[pi][pj],p[i][j])] = {0,linf};
	//                 x  y         max_add       max_money  step
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			for(int pi = 1;pi <= i;pi++){
				for(int pj = 1; pj <= j;pj++){
					if(pi==i && pj == j) continue;
					
					if(dp[i-1][j][p[pi][pj]].sc != linf){
						int now = dp[i-1][j][p[pi][pj]].fs;
						int cnt = 1;
						//不断增加,直到有钱为止
						cnt+=((d[i-1][j] - now) / p[pi][pj]);
						now += ((d[i-1][j] - now) / p[pi][pj]) * p[pi][pj];

						while(now < d[i-1][j]){
							now += p[pi][pj];
							cnt++;
						}
						pii nw = {now - d[i-1][j] , dp[i-1][j][p[pi][pj]].sc + cnt};
						if(nw.sc < dp[i][j][max(p[pi][pj],p[i][j])].sc ||
						(nw.sc == dp[i][j][max(p[pi][pj],p[i][j])].sc && nw.fs > dp[i][j][max(p[pi][pj],p[i][j])].fs)){
							dp[i][j][max(p[pi][pj],p[i][j])]=nw;
						}						
					}if(dp[i][j-1][p[pi][pj]].sc!= linf){
						int now = dp[i][j-1][p[pi][pj]].fs;
						int cnt = 1;
						//不断增加,直到有钱为止
						cnt+=((r[i][j-1] - now) / p[pi][pj]);
						now += ((r[i][j-1] - now) / p[pi][pj]) * p[pi][pj];
						while(now < r[i][j-1]){
							now += p[pi][pj];
							cnt++;
						}
						pii nw = {now - r[i][j-1] , dp[i][j-1][p[pi][pj]].sc + cnt};
						if(nw.sc < dp[i][j][max(p[pi][pj],p[i][j])].sc ||
						(nw.sc == dp[i][j][max(p[pi][pj],p[i][j])].sc && nw.fs > dp[i][j][max(p[pi][pj],p[i][j])].fs)){
							dp[i][j][max(p[pi][pj],p[i][j])]=nw;
							
						}						
					}
				}
			}
		}
	}
	int minn = 1e18;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			minn = min(minn,dp[n][n][p[i][j]].sc);
		}
	}
	cout<<minn<<endl;
}
signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int T=1;
//	cin >> T;
	while(T--) solve();
	return 0;
}

2024/3/11 19:36
加载中...