DP Review 1

DP Review 1

这个dp啊,我就是直接用题目来说了

USACO3.1.2 总分

洛谷上面的链接
这一道题是一道比较容易看出来的题目,就是设f[n]代表时间为n的时候的最大的分数,然后就枚举第几个种类以及时间就可以了(就是背包问题啊)

Code

#include<bits/stdc++.h>
#define maxn 10002
#define Int64 long long
using namespace std;

int M,N;//时间,种类
int t[maxn],s[maxn];//耗时,分数
Int64 f[maxn];

int main(){
    scanf("%d%d",&M,&N);
    for(int i=1;i<=N;i++){
        scanf("%d%d",&s[i],&t[i]); 
    }
    
    memset(f,0,sizeof(f));
    
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            if(j>=t[i]){
                f[j]=max(f[j],f[j-t[i]]+s[i]);
            }
        }
    }
    cout<<f[M];
    
    return 0;
} 

逃亡的准备

Description

在《Harry Potter and the Deathly Hallows》中,Harry Potter他们一起逃亡,现在有许多的东西要放到赫敏的包里面,但是包的大小有限,所以我们只能够在里面放入非常重要的物品,现在给出该种物品的数量、体积、价值的数值,希望你能够算出怎样能使背包的价值最大的组合方式,并且输出这个数值,赫敏会非常地感谢你。

Input

第一行有2个整数,物品种数n和背包装载体积v。  第 2 行到 n+1 行每行3个整数,为第i种物品的数量m、体积w、价值s。.

Output

仅包含一个整数,即为能拿到的最大的物品价值总和。

Sample Input

2 10
3 4 3
2 2 5

Sample Output

13

Analysis

这一道题啊,一眼就可以看出是一个多重背包问题所以说就可以写出核心的代码

for(int i=1;i<=n;i++){
        for(int j=v;j>=1;j--){
            for(int k=1;k<=m[i];k++){
                if(j>=c[i]*k){
                    f[j]=max(f[j],f[j-k*c[i]]+k*p[i]);
                }
            }
        }
    } 

如果你把上面那一段交上去,毫无疑问,你就会TLE几个点
为了优化,中间你应该写成

if(j>=c[i]*k){
    f[j]=max(f[j],f[j-k*c[i]]+k*p[i]);
}
    else break;

因为既然都比C[i]*k小了,接着k还要继续增大,这不是浪费时间吗,
那么我们就大胆而合理的AC了这道题
这样就可以完美地解决超时的问题了啦

最大约数和

洛谷的链接

Analysis

这一道题根据题意,你首先要知道1~N和之间每一个数的约数的和,可以通过下面一个函数来解决

inline void div(int x){

    for(int i=2;i<=sqrt(x);i++){
        if(!(x%i)){
            factor_sum[x]+=(i+x/i);
            if(i==sqrt(x))factor_sum[x]-=i;
        }
    }
    factor_sum[x]++;
    
}
//获取每一个数的约数和 

然后呢,就需要dp了,这一个自己感觉是有点像是一个完全背包,但是这并不代表这是一个完全背包的题,我的意思是,在累加的过程中,你选择的累加的数是有无限多个,因此从前往后枚举就可以了

for(int i=1;i<=n;i++){
    for(int j=1;j<=i;j++){
        factor_sum[i]=max(factor_sum[i],factor_sum[j]+factor_sum[i-j]);
    }
}

想到了这些,就可以AC

转载于:https://www.cnblogs.com/perisino/p/10405796.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值