ABC404E 题解

E. Bowls and Beans

题意

N N N 个碗排成一排,编号为 0 ∼ N − 1 0\sim N-1 0N1,碗 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 iCii1 中的任意碗里,并且可以任意分配每个碗里放几颗。

最初碗 0 0 0 中没有豆子,问:将所有豆子都移到碗 0 0 0 中,最少需要多少步。

思路

N ≤ 2000 N \le 2000 N2000,考虑 O ( n 2 ) O(n^2) O(n2) 动态规划。

动态规划基本三步:

  1. 设计 DP \text{DP} DP 状态:

​ 定义 f i f_i fi 表示将编号 ≥ i \ge i i 的所有碗中的豆子全部移到碗 i i i 中的最小步骤;

  1. 初始化:

​ 设最后一个有豆子的碗为 p p p,则对于 i = p ∼ n − 1 i=p\sim n-1 i=pn1 f i = 0 f_i=0 fi=0(不需要操作),其余初始 f i = ∞ f_i=\infty fi=

  1. 转移顺序及转移方程:

    顺序:由于每个碗里的豆子只能往前移,为避免转移产生影响后续计算,应从后往前转移;

    满足以下条件时, 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 jiCj

    • 条件3:若 i − j ≥ 2 i-j\ge2 ij2 i + 1 i+1 i+1 j − 1 j-1 j1 之间的任何一个碗都没有豆子(否则不可能一步就完成 j → i j \rightarrow i ji 的操作)。

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);//为了满足条件2
			if(a[j]) break;//为了满足条件3,只要遇到了有豆子的碗就退出
		}
	}
	cout<<f[0]<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值