zoukankan      html  css  js  c++  java
  • 2020杭电多校第四场 1003-Contest of Rope Pulling 01背包+随机化

    1003-Contest of Rope Pulling

    题意

    有两个班级,分别有(n)(m)个学生,每个学生有两个值(w_i)(v_i),表示力量和美丽度,问从两个班级各选出一些人使两个班的总力量相等,且所有学生的总美丽度最大。

    分析

    因为力量累加起来会很大,我们可以(dp)两个班级的力量差,将第二个班级的学生的(w_i)改为(-w_i),然后(dp[i][j]),表示前(i)个学生的力量和为(j)时的最大美丽度和,转移如下:

    [dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]) ]

    第一维是可以滚动的。

    因为最优解的力量差是在(0)附近震荡的,可以对力量差设一个阈值,将这(n+m)个学生随机重排一下之后这个阈值的期望值就会很小,大概是(10^5)左右。

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<sstream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<bitset>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<set>
    #include<map>
    #define rep(i,x,n) for(int i=x;i<=n;++i)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=1e5+10;
    const ll inf=1e18;
    const int base=50002;
    int T;
    int n,m;
    ll dp[2][100010];
    pii a[1010],b[1010],c[2010];
    int main(){
      //ios::sync_with_stdio(false);
      //freopen("in","r",stdin);
      std::mt19937 generator(time(0));
      scanf("%d",&T);
      while(T--){
        scanf("%d%d",&n,&m);
        rep(i,1,n){
          scanf("%d%d",&a[i].fi,&a[i].se);
        }
        rep(i,1,m){
          scanf("%d%d",&b[i].fi,&b[i].se);
        }
        rep(i,1,m) b[i].fi=-b[i].fi;
        int tot=0;
        rep(i,1,n) c[++tot]=a[i];
        rep(i,1,m) c[++tot]=b[i];
        ll ans=0;
        std::shuffle(c+1,c+tot+1,generator);
        rep(i,0,1) rep(j,0,2*base) dp[i][j]=-inf;
        dp[0][base]=0;
        int st=1;
        rep(i,1,tot){
          rep(j,0,2*base) if(j-c[i].fi>=0&&j-c[i].fi<=2*base){
              dp[st][j]=max(dp[st][j],dp[st^1][j-c[i].fi]+c[i].se);
            }
          rep(j,0,2*base) dp[st][j]=max(dp[st][j],dp[st^1][j]);
          rep(j,0,2*base) dp[st^1][j]=-inf;
          st^=1;
        }
        printf("%lld
    ",dp[st^1][base]);
      }
      return 0;
    }
    
  • 相关阅读:
    html 底部虚线
    C# 写入二进制文件
    js document 触发按键事件
    python之工作举例:通过复制NC文件来造数据
    python之多线程举例
    python之发送HTML内容的邮件
    python之打印日志logging
    python之查询指定目录下的最新文件
    python之datetime类
    python之Counter类:计算序列中出现次数最多的元素
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13409726.html
Copyright © 2011-2022 走看看