杭电多校第四场 1003 Contest of Rope Pulling(随机化+动态规划)

Posted ucprer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了杭电多校第四场 1003 Contest of Rope Pulling(随机化+动态规划)相关的知识,希望对你有一定的参考价值。

题意:

多组输入,给定a,b两个数组,长度分别为n,m。每个元素有两个值:wi,vi,要求从两个数组中分别选出一个子数组,使得两个子数组的wi和相同,并使总的vi之和最大。

数据范围:n,m<=1e3,wi<=1e3,vi<=1e9,(sum(n+m)<=1e4)

解法:

很容易想到分别对两个数组进行背包,求出每种可能重量和的价值最大值,然后遍历两个dp数组求出价值和的最大值,复杂度为(n^2*wi),但是这样一组样例就有1e9,5组就有5e9,稳TLE了。

首先想到将两个背包合并为一个,即对b数组的wi取反加入到a数组中,答案就是对a数组做背包后dp[0]的值。(由于数组下标不能为负,需要对每个状态加上一个base值,使所有状态对应的下标为正)。

合并为一个背包后,可以发现最后需要的答案就是一个dp[0](为方便描述暂且不加上base值),如果对所有可能的重量的状态进行转移,会浪费掉大量对答案不一定有贡献的时间,那么如何避免这种情况呢?应该采用对合并后的a数组进行随机化的方法,基于一个随机化的数组,绝对值很大的状态再转移回dp[0]的概率是很低的,因此可以不考虑绝对值很大的状态,即减小dp数组的范围,这样答案也是有很大的几率是正确的。

算一下时间复杂度,评测机能跑5s,就是5e8的计算量,由于总和有限制,对于n=1000,m=1000=这种数据最多有5组,因此一组数据计算量是1e8,背包要做n+m次,每次计算量为5e4(但是这样可能会wa,要开大一点开1e5,评测机能3s稳过)

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1e15;
const int maxn=2e3+5;
const int maxdp=1e5+5;
const int base=5e4;
const int lim=1e5;
pair<int,int> pi[maxn];
void debug(ll *a,int l,int r){
    for(int i=l;i<=r;i++){
        printf("%d ",a[i]);
    }
    puts("");
}
ll w[maxn],v[maxn];
ll temp[maxdp];
ll dp[maxdp];//dp[i]:i-base重量的最大价值
void init(){
    fill(dp,dp+maxdp,-INF);
    fill(temp,temp+maxdp,-INF);
    dp[base]=0;
    temp[base]=0;
}
int main () {
    srand(time(0));
    int T;
    scanf("%d",&T);
    while(T--){
        int n,m;
        scanf("%d%d",&n,&m);
        init();
        for(int i=1;i<=n+m;i++){
            scanf("%d%d",&pi[i].first,&pi[i].second);
            if(i>n){
                pi[i].first=-pi[i].first;
            }
        }
        random_shuffle(pi+1,pi+1+n+m);
        for(int i=1;i<=n+m;i++){
            w[i]=pi[i].first;
            v[i]=pi[i].second;
        }
        for(int i=1;i<=n+m;i++){
            for(int j=min(lim,(int)lim+(int)w[i]);j-w[i]>=0;j--){
                if(dp[j-w[i]]!=-INF){
                    temp[j]=max(dp[j],dp[j-w[i]]+v[i]);
                }
            }
            for(int j=0;j<=maxdp-1;j++){
                dp[j]=temp[j];
            }
        }
        printf("%lld
",dp[base]);
    }
}

以上是关于杭电多校第四场 1003 Contest of Rope Pulling(随机化+动态规划)的主要内容,如果未能解决你的问题,请参考以下文章

2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

2020杭电多校第四场 Go Running 最小点覆盖等于二分图最大匹配数

杭电2018多校第四场(2018 Multi-University Training Contest 4) 1005.Problem E. Matrix from Arrays (HDU6336) -

2019 杭电多校 第四场

2018杭电多校第二场1003(DFS,欧拉回路)

2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分