码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-07-31 18:01:31      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:temp   pair   ++   方法   shuf   can   i+1   max   pull   

题意:

多组输入,给定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\n",dp[base]);
    }
}

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

标签:temp   pair   ++   方法   shuf   can   i+1   max   pull   

原文地址:https://www.cnblogs.com/ucprer/p/13410423.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!