牛客每日一题NC19158失衡天平 (动态规划dp)
https://ac.nowcoder.com/acm/problem/19158
题目描述
终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个神秘老人走到她面前答应无偿给她武器,但老人有个条件,需要将所选武器分别放在天平的两端,若天平平衡则可以将天平上的所有武器拿走,还好这个天平锈迹斑斑,只要两端重量相差小于等于m就会保持平衡,Alice傻傻的认为越重的武器越好,求Alice最多能拿走的武器总重量。(不限操作次数)
输入描述:
第一行2个整数 n, m;
第二行n个整数x,分别表示n件武器的重量。
1 <= n <= 100; 0 <= m <= 100; 1 <= x <= 100;
输出描述:
一个整数,表示Alice最多能拿走的武器总重量。
示例1
输入
5 4 1 5 61 65 100
输出
132
说明
可以称两次,第1次:(1 ; 5),第二次(61 ; 65)。
题意:给n个武器的重量,放在天平两端相差不超过m就可以拿走,问最多能拿走多少重量?
题解:我们用dp[i][j]表示到第i个物品重量相差为j的重量最大值
转移状态 ① 不要这个武器 dp[i][j]=dp[i-1][j];
②把这个武器放在天平右边 dp[i][ j+a[i] ] = max(dp[i][ j+a[i] ] , dp[i-1][j] +a[i] );
③把这个武器放在天平左边 dp[i][ j- a[i] ] = max(dp[i][ j- a[i] ] , dp[i-1][j] +a[i] );
因为重量差值可能会出现负数,我们倍长数组
起点 dp[0][10000]=0;
答案就是对所有dp[n][ ] 取max;
#include <bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int maxn= 107; int x[maxn]; int dp[maxn][2*maxn*maxn]; int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&x[i]); } memset(dp,-inf,sizeof(dp)); dp[0][10000]=0; for(int i=1;i<=n;i++){ for(int j=0;j<=20000;j++){ dp[i][j]=max(dp[i-1][j], dp[i][j] ); if(j+x[i]<=20000) dp[i][j+x[i]]=max(dp[i][j+x[i]],dp[i-1][j]+x[i]); if(j-x[i]>=0 ) dp[i][j-x[i]] =max(dp[i][j-x[i]] , dp[i-1][j]+x[i] ); } } int ans=0; for(int i=0;i<=m;i++){ ans=max(ans,dp[n][10000+i]); ans=max(ans,dp[n][10000-i]); } printf("%d\n",ans); return 0; }