题解 # 观察易知,若想用最小的时间覆盖一段线段,那么结束时的位置一定在线段的左端点或右端点。那么我们的 dp 状态就可以设为dpl,r,pdp_{l,r,p}dpl,r,p,代表覆盖从 l 到 r 的线段所用的最短时间并且以左端点结尾(p=0),右端点结尾(p=1)。 状态转移是不难想的,dpl,r,0dp_{l,r,0}dpl,r,0可以由dpl+1,r,0dp_{l+1,r,0}dpl+1,r,0或dpl+1,r,1dp_{l+1,r,1}dpl+1,r,1得到,同理dpl,r,1dp_{l,r,1}dpl,r,1可以由dpl,r−1,0dp_{l,r-1,0}dpl,r−1,0或dpl,r−1,1dp_{l,r-1,1}dpl,r−1,1得到,别忘了判断一下是否在规定的时间之内。具体转移看代码~ Code # #include <bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); ++i) #define for1(i, n) for (int i = 1; i <= int(n); ++i) #define ms(a, x) memset(a, x, sizeof(a)) #define F first #define S second #define all(x) (x).begin(),(x).end() #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int INF = 0x3f3f3f3f; mt19937 gen(chrono::steady_clock::now().time_since_epoch().count()); const int N=1005; int dp[N][N][2]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin>>n; vector<int> p(n+1),t(n+1); ms(dp,INF); for1(i,n){ cin>>p[i]; dp[i][i][0]=dp[i][i][1]=0; } for1(i,n) cin>>t[i]; for(int len=2;len<=n;len++){ for(int l=1;l+len-1<=n;l++){ int r=l+len-1; int t1=min(dp[l+1][r][0]+p[l+1]-p[l],dp[l+1][r][1]+p[r]-p[l]); int t2=min(dp[l][r-1][0]+p[r]-p[l],dp[l][r-1][1]+p[r]-p[r-1]); if(t1<=t[l]) dp[l][r][0]=t1; if(t2<=t[r]) dp[l][r][1]=t2; } } int ans=min(dp[1][n][0],dp[1][n][1]); cout<<(ans==INF?-1:ans); return 0; }