这题状态很好想,而且向量按斜率降序排一下,就行了,只是不用滚动数组,就超时,也是无语了、
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define rep(i,n) for(int (i)=0;(i)<n;(i)++) #define rep1(i,x,y) for(int (i)=x;(i)<=y;(i)++) const int inf = 1e9; const int N = 55; struct point{ int x,y; point(int x=0,int y=0):x(x),y(y){} bool operator<(const point& rhs)const{ return rhs.x*y>=rhs.y*x; } }a[N]; int area(int h,point b){ return (b.y+h*2)*b.x; } int d[2][N][N*N],he[N]={0}; int n,k; int dp(int lim){ for(int i=1;i<=n;i++) he[i]=he[i-1]+a[i].y; for(int j=0;j<=k;j++) for(int h=0;h<=lim;h++){ if(j==k) d[0][j][h]=0; else d[0][j][h] = -inf; } int pre=0,now=1; for(int i=n-1;i>=0;i--){ for(int j=0;j<=k;j++) for(int h=0;h<=lim;h++){ d[now][j][h]=d[pre][j][h]; if(j<k && h+a[i+1].y<=lim) d[now][j][h]=max(d[now][j][h],d[pre][j+1][h+a[i+1].y]+area(h,a[i+1])); } now^=1; pre^=1; } return d[pre][0][0]; } int main() { int T,kase=1; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&k); rep1(i,1,n) scanf("%d %d",&a[i].x,&a[i].y); sort(a+1,a+1+n); int lim = 0; for(int i=n,j=1;j<=n;i--,j++) lim+=a[i].y; printf("Case %d: %d\n",kase++,dp(lim)); } return 0; } /* 2 4 3 3 5 0 2 2 2 3 0 4 2 3 5 0 2 2 2 3 0 */