题意:
思路:
这个是01背包的模板题
首先我们可以考虑搜索
n个武器,每个武器都有三个决策:放左边,放右边,不放
因此这样就构成了搜索的状态图(不是DP的状态图!)
这样每个结点都会有三个出边,三条出边就代表着三个决策
然而,我们注意到,我们只考虑两个参数:由于最优子结构,整体最优一定是由局部最优转移而来,而如果我们这样搜索就会产生很多个一定不是最优的无用状态。而且,我们只需考虑搜索到的每个状态的总重量和左右盘子重量之差,因此,搜索到的很多形式上不同的状态实际上可以归成一类状态,这个其实就是无后效性原理。把这些搜索到的状态合并在一起构成的状态就是DP的状态,这样归并之后产生的状态图就是DP状态图。
构成图之后就可以考虑在DP的状态图中转移了,我们定义dp[i][j]为前i样物品进行选择后,左右重量差为j的时候最大重量是多少
那么它可以由三个状态转移过来:前面那个选了左,前面那个选了右,前面那个没选
因此转移方程为:
dp[i][j]=max(dp[i-1][j],max(dp[i-1][abs(j-a[i])]+a[i],dp[i-1][j+a[i]]+a[i]));
Code:
#include <bits/stdc++.h>
using namespace std;
const int mxn=1e5+10;
int n,m;
int a[mxn],dp[110][mxn];
int main(){
scanf("%d%d",&n,&m);
memset(dp,128,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=mxn;j++) dp[i][j]=max(dp[i-1][j],max(dp[i-1][abs(j-a[i])]+a[i],dp[i-1][j+a[i]]+a[i]));
}
/*for(int i=1;i<=n;i++){
for(int j=0;j<mxn;j++) printf("%d%c",dp[i][j],j==mxn-1?'\n':' ');
}*/
int ans=0;
for(int i=0;i<=m;i++){
ans=max(ans,dp[n][i]);
}
printf("%d\n",ans);
return 0;
}