[NC19158] 失衡天平
1 2 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个物品组合放置之后的两边之差
那么我们可以得到一个递推的想法:
1 2 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代码
1 2 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; }
|