1. 程式人生 > 實用技巧 >牛客每日一題NC19158失衡天平 (動態規劃dp)

牛客每日一題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; }
View Code