看到题目按照贪心的去做,wa了好几发,最后参考别人的思路;
按照0-1背包去做,首先得到w,v的值,因为根据式子h*h-h*c-c*c,可知,在h>c时c固定时,h越大越好,在h<c时式子的值为0,不用考虑,所以,当c固定时,h越大越好,(0-1背包的靠近),总的容量是每个c的和,不超过500*100,最后要转化成式子的值。
参考代码:
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;
#define ll long long
const int maxn=50100;
ll h[maxn],c[maxn];
ll dp[maxn];
int main()
{
freopen("C:\\Users\\Administrator\\Desktop\\a.txt","r",stdin);
ll n,t,maxc;
ll C,H;
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
memset(dp,0,sizeof(dp));
maxc=0;
for(int i=0;i<n;i++)
scanf("%lld%lld",&h[i],&c[i]),maxc+=c[i];
for(int i=0;i<n;i++)
for(int j=maxc;j>=c[i];j--)
dp[j]=max(dp[j],dp[j-c[i]]+h[i]);//状态转移方程
ll ans=0;
for(int i=0;i<=maxc;i++)
ans=max(ans,dp[i]*dp[i]-dp[i]*i-i*i); //转化得到式子的值
printf("%lld\n",ans);
}
return 0;
}
除去题目而言,可以学习一下0-1背包,
从下往上,从左往右填表
一般0-1背包方程
for(int i=n;i>=1;i--)
for(int j=0;j<=c;j++)
{
dp[i][j]= (i==n ? 0:dp[i+1][j]);
if(j>=v[i]) dp[i][j]=max(dp[i][j],dp[i+1][j-v[i]]+w[i]);
}
poj题目:0-1背包3624-Charm Bracelet,3628-Bookshelf 2