失衡天平 DP

失衡天平

https://ac.nowcoder.com/acm/problem/19158

一看题意首先想了求最值,那么就是二分 但是操作过程中是很灵活的,然后果断pass掉,然后DP,很明确题目就是三种情况,要么放左边,要么不放,要么放右边,反正最后取得的武器必然左右两边差值不过M,那么就要想DP方程式,DP[i][j]=代表前i个物品左右最多相差j的质量,我们可以很容易想到要是本次不放那么就是dp[i][j]=dp[i-1][j],直接就是继承上一次的,然后就是放左边,我们应该是dp[i][j+x]=max(dp[i-1][j]+x),放在右边那就是dp[i][abs(j-x)]=dp[i-1][j]+x;

#include <bits/stdc++.h>
#define fio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define debug(x) cout << #x << ": " << x << endl;
#define debug1(x) cout<<x<<endl;
#define ll long long
#define ull unsigned long long
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#define mse(a,b) memset(a,b,sizeof a);
#define fro for
#define it int
using namespace std;
const int maxx=1e6+100;
const int mod=1e9+7;
ll gcd(ll a,ll b)
{
    while(b^=a^=b^=a%=b);
    return a;
}
int ans[110];
int dp[110][10100];///dp[i][j]选择前面i个物品然后最大的差值为j
//ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
//inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
int main()
{
    int m,n;
    cin>>n>>m;
    int sum=0;
        mse(dp,-0x3f3f);
        dp[0][0]=0;
    for(it i=1;i<=n;i++)
        {
            cin>>ans[i];
            for(int j=0;j<=10000;j++)
        {
            int x=ans[i];
             dp[i][j] = max(dp[i][j], dp[i-1][j]);///左右都不加,直接继承上一次的
            if(j+ans[i]<=10000)
                dp[i][j+x]=max(dp[i][j+x],dp[i-1][j]+x);
            dp[i][abs(j-x)]=max(dp[i][abs(j-x)],dp[i-1][j]+x);
        }
        }
        sum=0;
        for(int i=1;i<=m;i++)
           sum=max(sum,dp[n][i]);
        cout<<sum<<endl;
    return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务