UVA - 12589(learning vector dp)

这题状态很好想,而且向量按斜率降序排一下,就行了,只是不用滚动数组,就超时,也是无语了、

#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
*/


你可能感兴趣的:(UVA - 12589(learning vector dp))