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

闫氏DP分析法

时间:2021-05-24 08:16:26      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:win   queue   using   根据   选择   表示   include   href   i++   

思路

将动态规划化为两个阶段
1.状态表示
f[i]表示的集合状态方程 属性:Max,Min,Count
2.状态计算
将f[i]分为几个子集去计算,要不重复不遗漏。如果是求Max,Min可重复
一般找最后一个不同点划分集合。

01背包问题

https://www.acwing.com/problem/content/2/
分析:
状态表示:
f(i,j)表示所有只考虑前i个物品,总体积不超过j的选法集合
属性:Max 集合中的最打价值
状态计算:
根据最后一个不同点区分子集,一个是所有不选第i个物品的集合 f(i-1,j)
一个是所有选i物品的集合(不重复,不遗漏) f(i-1,j-v[i])+w[i]

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
int N,V;
int w[1005],v[1005];
int dp[1005];
int main(){
    cin>>N>>V;
    for(int i=1;i<=N;i++){
        cin>>v[i]>>w[i];
    }
    for(int i=1;i<=N;i++){
        for(int j=V;j>=v[i];j--){
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }
    }
    cout<<dp[V];

  return 0;
}
//  freopen("testdata.in", "r", stdin);

完全背包问题

https://www.acwing.com/problem/content/3/

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
int N,V;
int w[1005],v[1005];
int dp[1005];
int main(){
    cin>>N>>V;
    for(int i=1;i<=N;i++){
        cin>>v[i]>>w[i];
    }
    for(int i=1;i<=N;i++){
        for(int j=v[i];j<=V;j++){//没有向上面将j倒着循环。这样在计算dp[j]时保证dp[j-v[i]]被计算过,即前面的最优解是满足可以选择无数次同一个物品条件
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }
    }
    cout<<dp[V];

  return 0;
}
//  freopen("testdata.in", "r", stdin);

石子合并

https://www.acwing.com/problem/content/284/
1.状态表示
f(i,j)表示所有将i,j合并成一段的集合
属性:Min
状态计算:
第一堆以k为终点 可以划分从i到j-1 数量的集合

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 305;
int f[N][N];
int s[N],n;
int main()
{
    cin>>n;
    for (int i = 1; i <= n; i ++ ){
        cin>>s[i];
        s[i]+=s[i-1];
    }
    for(int len=2;len<=n;len++){
        for(int i=1;i+len-1<=n;i++){
            int j=i+len-1;
            f[i][j]=1e8;
            for(int k=i;k<j;k++){
                f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
            }
        }
    }
    cout<<f[1][n]<<endl;
}

闫氏DP分析法

标签:win   queue   using   根据   选择   表示   include   href   i++   

原文地址:https://www.cnblogs.com/OfflineBoy/p/14765929.html

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