CF1456 D. Cakes for Clones
阿新 • • 發佈:2020-11-30
在一個數軸上,在\(t_i\)時刻會掉下一個物品於\(x_i\)。你需要按時接住所有的物品。從\(0\)開始,每單位時間可以移動一單位距離。你可以在任意時刻放一個克隆,克隆可以接住恰好掉在它上面的物品,且克隆不能動。在放一個克隆的時候上一個克隆會消失。
問是否可以接住所有的物品。
\(t_i,x_i\)互不相同。
\(n\le 5000\)
比賽的時候想了個比較冗餘的做法最終也沒有寫出來。
題解做法陽間多了:設\(g_i\)表示到達\(i\)且此時的克隆變得沒用了的最小時間,\(f_{i,j}\)表示剛好按時走到\(i\)並且克隆在\(j\)是否可行。
\(g_i\)轉移:1. 在\(i\)丟個克隆然後跑到\(i+1\)
\(f_{i,j}\)轉移:
- \(j\neq i+1\)時,直接跑到\(i+1\),即\(f_{i+1,j}\)
- \(j=i+1\)時:(1) 跑到\(i+2\),即\(g_{i+2}\)。(2) 跑到\(k\)放克隆再跑到\(i+2\),即\(f_{i+2,k}\)。
可以發現這已經涵蓋了最優的情況。
\(O(n^2)\)。
using namespace std; #include <cstdio> #include <cstring> #include <algorithm> #define N 5005 int n; int t[N],x[N]; bool f[N][N]; int g[N]; bool work(){ memset(g,127,sizeof g); g[0]=0; for (int i=0;i<n;++i){ if (g[i]<=t[i]){ g[i+1]=min(g[i+1],max(g[i]+abs(x[i]-x[i+1]),t[i])); for (int j=i+2;j<=n;++j) f[i+1][j]|=(max(g[i]+abs(x[i]-x[j]),t[i])+abs(x[j]-x[i+1])<=t[i+1]); } for (int j=i+2;j<=n;++j) f[i+1][j]|=(f[i][j] && t[i]+abs(x[i]-x[i+1])<=t[i+1]); if (f[i][i+1] && i+2<=n){ g[i+2]=min(g[i+2],max(t[i]+abs(x[i]-x[i+2]),t[i+1])); for (int k=i+3;k<=n;++k) f[i+2][k]|=(max(t[i]+abs(x[i]-x[k]),t[i+1])+abs(x[k]-x[i+2])<=t[i+2]); } } return g[n]<=t[n] || f[n-1][n]; } int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d%d",&t[i],&x[i]); if (work()) printf("YES\n"); else printf("NO\n"); return 0; }