ABC404E 题解
E. Bowls and Beans
题意
N N N 个碗排成一排,编号为 0 ∼ N − 1 0\sim N-1 0∼N−1,碗 i i i 中有 A i A_i Ai 个豆子,上面写着一个数字 C i C_i Ci。
每次操作可以将碗 i i i 里的豆子可以放到之前 i − C i ∼ i − 1 i-C_i \sim i-1 i−Ci∼i−1 中的任意碗里,并且可以任意分配每个碗里放几颗。
最初碗 0 0 0 中没有豆子,问:将所有豆子都移到碗 0 0 0 中,最少需要多少步。
思路
N ≤ 2000 N \le 2000 N≤2000,考虑 O ( n 2 ) O(n^2) O(n2) 动态规划。
动态规划基本三步:
- 设计 DP \text{DP} DP 状态:
定义 f i f_i fi 表示将编号 ≥ i \ge i ≥i 的所有碗中的豆子全部移到碗 i i i 中的最小步骤;
- 初始化:
设最后一个有豆子的碗为 p p p,则对于 i = p ∼ n − 1 i=p\sim n-1 i=p∼n−1, f i = 0 f_i=0 fi=0(不需要操作),其余初始 f i = ∞ f_i=\infty fi=∞;
-
转移顺序及转移方程:
顺序:由于每个碗里的豆子只能往前移,为避免转移产生影响后续计算,应从后往前转移;
满足以下条件时, f i = min ( f i , f j + 1 ) f_i=\min(f_i,f_j+1) fi=min(fi,fj+1):
-
条件1: j > i j>i j>i;
-
条件2:碗 j j j 的豆子可以移到碗 i i i 中,即 j − i ≤ C j j-i \le C_j j−i≤Cj;
-
条件3:若 i − j ≥ 2 i-j\ge2 i−j≥2, i + 1 i+1 i+1 到 j − 1 j-1 j−1 之间的任何一个碗都没有豆子(否则不可能一步就完成 j → i j \rightarrow i j→i 的操作)。
-
C++ 代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=3e18;
const int maxn=2005;
int n;
int c[maxn],f[maxn];
bool a[maxn];
signed main(){cin>>n;for(int i=1;i<n;i++) cin>>c[i];for(int i=1;i<n;i++) cin>>a[i];//初始化for(int i=0;i<n;i++) f[i]=inf;int pos;for(int i=n-1;i>=0;i--){f[i]=0;if(a[i]){pos=i-1;break;}}//转移for(int i=pos;i>=0;i--){//为了避免产生后效性,从后往前遍历for(int j=i+1;j<n;j++){//为了满足条件1,j=i+1开始if(j-i<=c[j]) f[i]=min(f[i],f[j]+1);//为了满足条件2if(a[j]) break;//为了满足条件3,只要遇到了有豆子的碗就退出}}cout<<f[0]<<endl;return 0;
}