先按力量排序,然后dp在前i个乌龟中j个乌龟可以重叠的最小重量,其实就是对于每个乌龟i选或是不选的问题。状态方程:dp[i, j] = min{dp[i, j-1], dp[i-1, j-1]+w[i]}.
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef struct Turtle
{
int wei, pow;
}TT;
TT tur[5610];
int dp[5610][5610];
int cmp(const void *a, const void *b)
{
TT *aa = (TT*)a;
TT *bb = (TT*)b;
return aa->pow - bb->pow;
}
int main()
{
#ifdef test
freopen("input.txt", "r", stdin);
#endif
int num = 1;
while(scanf("%d%d", &tur[num].wei, &tur[num].pow) != EOF)
{
dp[num][0] = 0;
++num;
}
--num;
for(int i=0; i<=num; ++i)
for(int j=1; j<=num; ++j)
dp[i][j] = 0x3FFFFFFF;
qsort(&tur[1], num, sizeof(tur[0]), cmp);
for(int i=1; i<=num; ++i)
for(int j=1; j<=i; ++j)
{
dp[i][j] = dp[i-1][j];
if(tur[i].pow-tur[i].wei>=dp[i-1][j-1] && dp[i-1][j-1]!=0x3FFFFFFF)
dp[i][j] = min(dp[i][j], dp[i-1][j-1]+tur[i].wei);
}
// for(int i=1; i<=num; ++i)
// {
// for(int j=1; j<=num; ++j)
// printf("%10d ", dp[i][j]);
// puts("");
// }
int ans;
for(ans=num; ans>=1; --ans)
if(dp[num][ans] != 0x3FFFFFFF)
break;
printf("%d\n", ans);
return 0;
}