养猪,大家都说是水题,然后今天考试我被卡掉了.
不仅我,大家都被卡掉啦.
于是我专门纪念这道所谓的“水题”.
大概是这样的一道题:
有人要卖猪,开始一天第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; }