关于养猪的详细讨论

养猪,大家都说是水题,然后今天考试我被卡掉了.

不仅我,大家都被卡掉啦.

于是我专门纪念这道所谓的“水题”.

大概是这样的一道题:

有人要卖猪,开始一天第i头猪的价值为ai,但每天第i头猪的价值会减少pi,若这头猪已经价值为负数了,那么这头猪的价值会变为0.

那么每天只能卖一头猪,问你k天后的最大价值.

那么这是一道DP题.

怎么DP,这明显有后效性.

那我们对它进行一个排序.

这个排序的准则是什么?

我们可以把这几头猪按照pi从大到小排序.

那么后面的猪一定是在前面的猪后面杀的.

证明的话可以用反证法:

假设猪i在猪j后面杀(i<j,已经排序过了),那么pi一定小于pj,肯定不会比猪i在前面杀划算.

若会到0,你就不用管了.

那么我们的排序准则就是以pi为第一关键字,ai为第二关键字排序.

所以我们的后效性问题解决了,我们就可以开始DP了.

我们设dp[i][j]表示前i头猪杀了j头的最大利润.

那么很明显我们可以列出方程:f[i][j]=max(f[i-1][j],f[i-1][j-1]+add).

其中add=max(0,a[i]-p[i]*(j-1)).

那么代码就好写了:

#include<bits/stdc++.h>
  using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
int n,k;
int dp[1001][1001]={0};
struct pig{
  int start,down;
}p[1001];
inline void into(){
  scanf("%d%d",&n,&k);
  rep(i,1,n)
    scanf("%d",&p[i].start);
  rep(i,1,n)
    scanf("%d",&p[i].down);
}
inline bool cmp(pig a,pig b){
  return a.down>b.down;
}
inline void work(){
  sort(p+1,p+1+n,cmp);
  rep(i,1,n)
    rep(j,1,min(i,k))
      dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+max(p[i].start-(p[i].down*(j-1)),0));
}
inline void outo(){
  printf("%d\n",dp[n][k]);
}
int main(){
  into();
  work();
  outo();
  return 0;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/79978161