E. Not Escaping 題解(dp)
阿新 • • 發佈:2022-01-16
題目連結
題目思路
這個題意有點難說清,還是自己讀比較好
這個題目我覺得是比較套路的,首先只有\(2*k+2\)個點有用
一個起點加上終點再加上梯子兩邊的起始點
問題是如何建邊是一個問題,暴力建邊顯然會達到\(n^2\)的
主要是在每一行內可以進行\(dp\)轉移,一次從左往右,一次從右往左,一個有點意思的\(dp\)
程式碼
不擺爛了,寫題#include<bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define debug cout<<"I AM HERE"<<endl; using namespace std; typedef long long ll; const ll INF=0x3f3f3f3f3f3f3f3f; const int maxn=2e6+5,inf=0x3f3f3f3f,mod=1e9+7; const double eps=1e-6; int n,m,k; int cnt; vector<pii> g[maxn]; pii to[maxn]; ll x[maxn]; ll dp[maxn]; void init(){ for(int i=1;i<=cnt;i++){ to[i]={0,0}; } cnt=0; for(int i=1;i<=n;i++){ g[i].clear(); } } signed main(){ int _;scanf("%d",&_); while(_--){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++){ scanf("%d",&x[i]); } init(); g[1].push_back({1,++cnt}); for(int i=1,a,b,c,d,h;i<=k;i++){ scanf("%d%d%d%d%d",&a,&b,&c,&d,&h); g[a].push_back({b,++cnt}); g[c].push_back({d,++cnt}); to[cnt-1]={cnt,-h};// 建邊 } g[n].push_back({m,++cnt}); for(int i=1;i<=cnt;i++){ dp[i]=INF; } dp[1]=0; for(int i=1;i<=n;i++){ sort(g[i].begin(),g[i].end()); int sz=g[i].size(); for(int j=1;j<sz;j++){ dp[g[i][j].se]=min(dp[g[i][j].se],dp[g[i][j-1].se]+x[i]*(g[i][j].fi-g[i][j-1].fi)); } for(int j=sz-2;j>=0;j--){ dp[g[i][j].se]=min(dp[g[i][j].se],dp[g[i][j+1].se]+x[i]*(g[i][j+1].fi-g[i][j].fi)); } for(int j=0;j<sz;j++){ dp[to[g[i][j].se].fi]=min(dp[to[g[i][j].se].fi],dp[g[i][j].se]+to[g[i][j].se].se); } } if(dp[cnt]>=1e18){ printf("NO ESCAPE\n"); }else{ printf("%lld\n",dp[cnt]); } } return 0; } // 3 1 3 2