F - Sensor Optimization Dilemma (atcoder.jp)
分析:一共两种物品,有n个需要覆盖的区间。
我们思考,如果成功方案存在时,对于一个区间,我们只需要知道在这个区间中,其中一种物品的个数就可以推算出另一种,数据范围个数为1e3,对于每个区间枚举个数是可行的,这时我们可以设计状态 dp[i][j] 到第 i 个区间时用了 j 个物品1时需要的物品2的个数。
转移方程是dp[i][j+k] =min(dp[i][j+k],dp[i-1][j]+tt) tt为当前区间减去k个物品1后,需要的物品2的个数。初始化dp数组是正无穷,dp[0][i]为0,最后计算答案是所有dp[n][i]<=物品2个数的方案的最小值
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N=1000010;
int a[N],l[2],k[2],c[2];
int dp[1010][1010];
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>l[0]>>c[0]>>k[0];
cin>>l[1]>>c[1]>>k[1];
memset(dp,0x3f,sizeof dp);
for(int i=0;i<1010;i++){
for(int j=0;j<1010;j++){
dp[i][j]=1e18;
}
}
for(int i=0;i<=k[0];i++)dp[0][i]=0;
for(int i=1;i<=n;i++){
int now=(a[i]+l[0]-1)/l[0];//当前区域最多花费
for(int j=0;j<=now;j++){
for(int kk=0;kk+j<=k[0];kk++){
int tt=(max((int)0,a[i]-j*l[0])+l[1]-1)/l[1];
dp[i][j+kk]=min(dp[i][j+kk],dp[i-1][kk]+tt);
}
}
}
int ans=1e18;
for(int i=0;i<=k[0];i++){
// cout<<dp[n][i]<<endl;
if(dp[n][i]<=k[1]) ans=min(ans,dp[n][i]*c[1]+i*c[0]);
}
if(ans==1e18) cout<<-1<<endl;
else cout<<ans<<endl;
}
·