牛客练习赛36-C: Rabbit的工作(2)(快速幂优化DP)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/86412671

链接:https://ac.nowcoder.com/acm/contest/328/C

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
Rabbit通过了上次boss的考核,现在她又遇到了一个问题。
Rabbit接到了K个任务,每个任务她可以自由选择用i天去完成 ( 1 i N ) (1≤ i≤ N) 。刁钻的boss想让Rabbit恰好用W天完成所有任务。
已知Rabbit用i天完成一个任务能让boss获得的满意度为 v i v_i (因为完成任务的质量不同),她想知道在满足boss要求的情况下能让boss获得的总满意度最大是多少。
输入描述:
第一行三个整数N,K,W。
第二行N个整数 v i v i v_i,v_i 表示用i天完成一个任务能让boss获得的满意度。
输出描述:
输出Rabbit在满足boss要求的情况下能让boss获得的总满意度最大是多少。
示例1
输入
3 3 5
6 2 4
输出
16
说明
Rabbit可以选择分别用1天,1天,3天完成这三个任务,最大满意度为6+6+4=16
备注:
2 N , K 2000 , K W m i n ( 4000 , 2 K ) 2≤ N,K≤ 2000,K≤ W≤ min(4000,2*K)
0 < v i 10000 0<v_i≤ 10000

思路:容易想到一个 n 3 n^3 的算法, d [ i ] [ j ] d[i][j] 表示前 i i 个任务总共花了 j j 天去完成的最大满意度。
需要优化。
因为 O ( n 3 ) O(n^3) 的DP是一个任务一个任务去转移的,所以我们考虑用快速幂的方式进行加速。即第一次转移选择一个任务,第二次选择两个任务,第三次选择四个任务。。。以此类推,比较类似多重背包的二进制优化。

#include<bits/stdc++.h>
using namespace std;
const int MAX=4e3+10;
const int MOD=1e9+7;
const int INF=1e9+7;
typedef long long ll;
int d[2][MAX];
int res[2][MAX];
int a[MAX];
int main()
{
    int n,m,w;
    cin>>n>>m>>w;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    memset(d,0,sizeof d);
    for(int i=0;i<=w;i++)res[0][i]=res[1][i]=-INF;
    res[0][0]=0;
    d[0][0]=-INF;
    for(int i=1;i<=n;i++)d[0][i]=a[i];
    int now=1,pre=0;
    while(m)
    {
        if(m&1)
        {
            for(int i=w;i>=0;i--)
            {
                res[now][i]=-INF;
                for(int j=0;j<=i;j++)res[now][i]=max(res[now][i],d[pre][j]+res[pre][i-j]);
            }
        }
        else for(int i=w;i>=0;i--)res[now][i]=res[pre][i];
        for(int i=w;i>=0;i--)
        {
            d[now][i]=-INF;
            for(int j=0;j<=i;j++)d[now][i]=max(d[now][i],d[pre][j]+d[pre][i-j]);
        }
        m/=2;
        pre^=1;
        now^=1;
    }
    cout<<res[pre][w]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/86412671