dp问题
先转换为权值数据,把权值数据化为K组(K1,K2……)数据
每一组数据相当于k等于1的子问题。
最后将最后k个加起来就是答案。
比如说样例
21 2
1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6
转化为权值数据为1 2 3 4 5 6
分成两组
1 3 5 k1
2 4 6 k2
k1子问题的答案是1+5=6
k2子问题的答案是2+6=8
最后问题的答案就是14。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,k;
const int MAX = 100010;
int dp[MAX]={0};
int ans[MAX]={0};
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)//赋权值
{
int buf;
scanf("%d",&buf);
ans[buf]++;
}
for(int i=0;i<=MAX;i++)//实际上是进行了k次dp,这里简写成一趟。
{
int buf1,buf2;
if(i-k<0)buf1=0;
else buf1=dp[i-k];
if(i-2*k<0)buf2=0;
else buf2=dp[i-2*k];
dp[i]=max(buf1,buf2+ans[i]);//状态转移方程
}
if(k==0)//特判一下k=0的情况
{
int Count=0;
for(int i=1;i<=MAX;i++)
if(ans[i]!=0)
Count++;
printf("%d",Count);
}
else{
int tot=0;
for(int i=0;i<k;i++)//将后面k个加起来就是答案
tot+=dp[MAX-i];
printf("%d\n",tot);
}
for(int i = 0;i<100;i++)
printf("%d ",dp[i]);
return 0;
}