【usaco2013 mar】奶牛的声音(mooomoo.pas/cpp/c)//2018.1.28

题目

题目描述
农夫约翰最近忘记他有多少奶牛了!于是他决定用一个特别新颖的方法来计算奶牛的数量。他在每块农田上都安装一个麦克风,通过麦克风的音量来计算每个农田上有多少奶牛。
约翰的N个农田是排成一条直线,每个农田上可能拥有不同种类的奶牛,奶牛的种类是B种,第i种奶牛每只奶牛都会发出Vi的音量。然后,由于农场里是经常有风的,风的方向是从左到右的,风使得奶牛的声音也从左到右吹了过去。如果声音在某块农田的音量是X,那么接下来风将把X-1音量的声音带到下一个(右边)那个农田上去。因此每块农田上的音量等于本身这块农田上奶牛发出的声音加上左边相邻的农田音量X-1。
给定从左到右每块农田上的音量,请帮助约翰计算他最少有多少数量的奶牛。
输入
第一行两个正整数N和B。
第2行到第B+1行,第i+1行的整数表示Vi。
第B+2行到第B+i+1行,表示从左到右每块农田上的监测到的音量。
输出
输出最少可能有多少奶牛,如果不能确定的话,就输出-1。
【数据规模】
1<=N<=100,1<=B<=20,1<=Vi<=100,每块农田上监测的音量不超过100000。

题目大意

奶牛的声音从左吹到右,逐次-1累加,有b种奶牛,第i种奶牛每只奶牛都会发出Vi的音量,最少可能有多少奶牛。


解题思路

一个完全背包的方案数问题,有一些变形,动态规划转移方程为 f[j+v[i]]=min(f[j]+1,f[j+v[i]]),f[i]表示音量为i时的方案数。


代码

#include
#include
#include
using namespace std; 
int n,b,v[101],x,f[300001]; 
int main()
{
  //freopen("mooomoo.in","r",stdin); 
  //freopen("mooomoo.out","w",stdout); 
  memset(f,0x7f,sizeof(f)); 
  scanf("%d%d",&n,&b); 
  for (int i=1;i<=b;i++)
   scanf("%d",&v[i]); 
   f[0]=0; //初始化
  for (int i=1;i<=b;i++ )
   for (int j=0;j<=100000;j++)
    f[j+v[i]]=min(f[j]+1,f[j+v[i]]); //完全背包的方案数
  int sl=0,ans=0; 
  for (int i=1;i<=n;i++)  
   {
     scanf("%d",&x); 
     if (!x) continue; //x=0时退出
     if (sl<=x&&f[x-sl]!=2139262143) ans+=f[x-sl]; //有此方案
      else if (sl<=x){  printf("-1");   return 0;}
     sl=x-1; //记录上一个数
   }  
   printf("%d",ans); 
  return 0; 
}

你可能感兴趣的:(动态规划(/线性DP))