牛客每日一題NC19158失衡天平 (動態規劃dp)
阿新 • • 發佈:2020-07-30
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(View Code"%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; }