[NC19158] 失衡天平
| 12
 3
 
 | 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K,其他语言524288K
 64bit IO Format: %lld
 
 | 
题目描述
终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个神秘老人走到她面前答应无偿给她武器,但老人有个条件,需要将所选武器分别放在天平的两端,若天平平衡则可以将天平上的所有武器拿走,还好这个天平锈迹斑斑,只要两端重量相差小于等于m就会保持平衡,Alice傻傻的认为越重的武器越好,求Alice最多能拿走的武器总重量。(不限操作次数)
输入描述:
第一行2个整数 n, m;
第二行n个整数x,分别表示n件武器的重量。
1 <= n <= 100; 0 <= m <= 100; 1 <= x <= 100;
输出描述:
一个整数,表示Alice最多能拿走的武器总重量。
示例1
输入
输出
说明
| 1
 | 可以称两次,第1次:(1 ; 5),第二次(61 ; 65)。
 | 
示例2
输入
输出
说明
| 1
 | 称一次,(10,20,30,40 ; 100)。
 | 
题解
题目解析
一道类似于背包的dp题.解题关键在于如何处理放置的物品.事实上,我们需要开一个二位数组作为dp数组.再就是找到这个问题的状态转移方程.
我们把背包的思想带入其中,使用了两个dp变量:
- 已经到了第i个物品
- 前i个物品组合放置之后的两边之差
那么我们可以得到一个递推的想法:
| 12
 3
 4
 5
 6
 7
 
 | dp[i][j]dp[i][j] = max(dp[i-1][j],max(dp[i-1][j-a[i]]+a[i],dp[i-1][j+a[i]]+a[i]);
 
 
 
 
 
 
 | 
那么我们顺理就可以得到它的状态转移方程了:
AC代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 
 | #include <iostream>#include <cstring>
 #include <cmath>
 #include <algorithm>
 const int MAXN = 110;
 using namespace std;
 
 int a[MAXN],dp[MAXN][MAXN*MAXN*2];
 
 int main(){
 int n,m;
 cin >> n >> m;
 for(int i=1;i<=n;i++) cin >> a[i];
 memset(dp,-0x3f3f3f3f,sizeof(dp));
 dp[0][0] = 0;
 for(int i=1;i<=n;i++){
 for(int j=0;j<=MAXN*MAXN*2;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]));
 }
 }
 int ans = 0;
 for(int i=0;i<=m;i++){
 ans = max(dp[n][i],ans);
 }
 cout << ans;
 return 0;
 }
 
 |