动态规划 0-1背包

/*
1267:【例9.11】01背包问题

时间限制: 1000 ms         内存限制: 65536 KB
提交数: 29440     通过数: 17699
【题目描述】
一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn,求旅行者能获得最大总价值。

【输入】
第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);

第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

【输出】
仅一行,一个数,表示最大总价值。

【输入样例】
10 4
2 1
3 3
4 5
7 9
【输出样例】
12
*/

#include <bits/stdc++.h>
using namespace std;
int w[35],c[35],f[205]; //w[]表示物品重量  c[]表示物品价值 f[]表示当前价值 
int main(){
    int m,n; //m表示背包容量 n表示物品个数 
    cin>>m>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i]>>c[i];
    } 
    for(int i=1;i<=n;i++){
        for(int j=m;j>=w[i];j--){
            if(f[j-w[i]]+c[i]>f[j])//j-w[j]表示放上当前i号物品剩余重量下 
                f[j]=f[j-w[i]]+c[i];                
                //cout<<f[j]<<" ";    
        }
       }
        cout<<endl; 

    cout<<f[m];
}

//广度优先算法实现 

/*
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
输入格式
第一行有 2 个整数 T(1≤T≤1000)和 M(1≤M≤100),用一个空格隔开,T 代表总共能够用来采药的时间,M 代表山洞里的草药的数目。
接下来的 M 行每行包括两个在 1 到 100 之间(包括 1 和 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出格式
输出在规定的时间内可以采到的草药的最大总价值。  
*/
#include <bits/stdc++.h>
using namespace std;
int t,m,w[101],v[101],f[1001]; //w表示菜药时间    v表示药的价值   f表示当前状态的价值 
int main(){
    cin>>t>>m;
    for(int i=1;i<=3;i++){
        cin>>w[i]>>v[i]; 
    }
    for(int i=1;i<=m;i++){
        //for(int j=w[i];j<=t;j++)
        for(int j=t;j>=w[i];j--)  //表示从后往前找 
        {
            if(f[j]<f[j-w[i]]+v[i])//当前状态小于我现在时间减去我花的时间的价值加现在的价值 
                f[j]=f[j-w[i]]+v[i]; 
        }
    }
    cout<<f[t];
    return 0;    


}
/*
金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1?5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
设第j件物品的价格为v[j],重要度为w[j],共选中了k件物品,编号依次为j1,j2,…,jk,则所求的总和为:v[j1] * w[j1]+ v[j2] *  w[j2] + …+ v[jk] * w[jk]。
请你帮助金明设计一个满足要求的购物单。
输入格式
第一行,为2个正整数,用一个空格隔开:n,m(其中N(<30000)表示总钱数,m(<25)为希望购买物品的个数。)
从第2行到第m+1行,第j行给出了编号为j?1的物品的基本数据,每行有2个非负整数v,p(其中v表示该物品的价格(v≤10000),p表示该物品的重要度(1?5)
输出格式
1个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<100000000)。

输入输出样例
输入
1000 5
800 2
400 5
300 5
400 3
200 2
**输出 **  
3900
*/
#include <bits/stdc++.h>
using namespace std;
int w[20001],v[26],c[20001],f[100000];
int main(){
    int m,n;
    cin>>m>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i]>>v[i];
        c[i]=w[i]*v[i];
    } 
    for(int i=1;i<=n;i++){
        for(int j=m;j>=w[i];j--){
            f[j] = max(f[j], f[j - w[i]] + w[i]*v[i]);
        //    if(f[j-w[j]]+w[i]*v[i]>f[j])
        //        f[j]=f[j-w[i]]+w[i]*v[i];
                
        }
       }
         
    cout<<f[m];
}

最长公共子序列

#include <iostream>
using namespace std;
#define N 100
int n,m;
char S1[N],S2[N];
int dp[N][N]; 
int b[N][N];

void LCSLength()
{
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++){
            dp[i][0]=0;
            dp[0][j]=0;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(S1[i]==S2[j]){   
                dp[i][j]=dp[i-1][j-1]+1;
                b[i][j]=1;  
            }
            else if(dp[i-1][j]>dp[i][j-1]){
                dp[i][j]=dp[i-1][j];
                b[i][j]=2; 
            }
            else{
                dp[i][j]=dp[i][j-1];
                b[i][j]=3;
            }     
        }
}

void LCS(int i,int j)
{
    if(i==0||j==0) 
        return;
    if(b[i][j]==1){
        LCS(i-1,j-1);
        cout<<S1[i]<<" ";//S2[j]
    }
    else if(b[i][j]==2)
        LCS(i-1,j);
    else
        LCS(i,j-1);
}
 
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>S1[i];
    cin>>m;
    for(int i=1;i<=m;i++)
        cin>>S2[i];
    LCSLength();
    cout<<"最长公共子序列长度是:"<<dp[n][m]<<endl;
    cout<<"最长公共子序列是:"; 
    LCS(n,m);
    cout<<endl; 
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            cout<<dp[i][j]<<" ";
        cout<<endl;
    }
    cout<<endl;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            cout<<b[i][j]<<" ";
        cout<<endl;
    }
}
 

最长不降子序列

#include<bits/stdc++.h> 
using namespace std;
int a[1001];
int f[1001];
int n;
int mx=-1; 
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i]; 
        f[i]=1;
    } 
    for(int i=2;i<=n;i++){
        for(int j=i-1;j>=1;j--){
            if(a[i]>=a[j]){
                f[i]=max(f[i],f[j]+1);
            }
        }
    }
    for(int i=1;i<=n;i++){
        mx=max(mx,f[i]);
    }
    cout<<mx;
    
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值