题目(声音辨数):
【题目描述】
一条线上有N个点,每个点可能若干B类动物,每个动物会发出声音,声音由左向右传递,如果第i个点发出的声音总和为L,则传到i+1为L-1,每个点的音量总和是上个点传递的音量加上这个点动物发出的声音总和
问:一共最少有多少个动物
【输入】
第一行是2个整数N,B,表示n个点,B类动物
接下来是B行,每行一个整数Vi表示每类动物发出的声音音量
接下来是N行,每行1个整数Li表示测到的每个点的音量 .
【输出】
1个整数表示最少的动物数,如果无法计算,输出-1。
【样例输入】
5 2
5
7
0
17
16
20
19
【样例输出】
4
【提示】
[样例解释]
1共5个点,2类动物。第一类动物发出音量为5,第二类发出音量为7 第一个点音量为0,所以这个点没用动物,第二个点音量17,说明有3个动物(5,5,7),第三个点音量16,刚好是上一个点的音量-1,说明这个点没有动物,第4个点音量20,减去上个点传递来的15的音量,动物发出的音量为5,说明有1个动物。第5个点音量为上个点传递来的,所以也没动物。最少有4只动物
数据规模:
对于30%数据N<=25,B<=5
对于50%数据N<=60,B<=15
对于100数据N<=100,B<=20,Vi<=100,每个点发出的声音音量<=10^5
分析:
由题,显然可以得到每个点动物发出的音量。。。
自然就想到要预处理每种音量最少有几只动物,直接求和输出即可。
那么,怎么预处理呢?
实际上就是一个简单的背包:
定义:dp[i]表示发出i的音量至少需要多少只动物
显然对于第j只动物有dp[i+v[j]]=min(dp[i]+1,dp[i+v[j]]);
再然后,就没然后了。。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=300;
const int M=1e5+10;
int n,b,a[N],d[N],t,ans,f[M];
void chushihua(){
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=1;i<=b;i++){
for(int j=a[i];j<=M;j++){
f[j]=min(f[j],f[j-a[i]]+1);
}
}
}
int main(){
cin>>n>>b;
for(int i=1;i<=b;i++)
cin>>a[i];
chushihua();
for(int i=1;i<=n;i++){
cin>>d[i];
if(i==1) t=d[i];
else{
t=d[i]-d[i-1];
if(d[i-1]>1) t++;
}
ans+=f[t];
}
if(ans>=0x3f3f3f3f) ans=-1;
cout<<ans<<endl;
return 0;
}