这题状态很好想,而且向量按斜率降序排一下,就行了,只是不用滚动数组,就超时,也是无语了、
#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
*/