zoukankan      html  css  js  c++  java
  • 背包简记

    背包问题的思想很不错,个人学习后收获很多。它是将一个问题分解成若干个子问题,并以解决子问题达到解决原问题的一种解题思想。接下来我准备复习一下3个简单的背包问题,以便日后回忆起来能很快。

    1:数塔问题

    题目:HDU 2084.

    解题思想:每下一层的最大值都能通过上一层的遍历得到,只要不断记录下一层就能得到的最低层的最大结果。(应该是背包问题中最简单的了吧);

    代码如下:

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int max(int a,int b)
     5 {
     6 return a>b?a:b;
     7 }
     8 
     9 int main()
    10 {
    11 int n;//多组输入; 
    12 while(cin>>n)
    13 {
    14 while(n--)
    15 {
    16 int m,a[105][105]={0},dp[105][105],ans=-1;
    17 cin>>m;//数塔层数; 
    18 for(int i=1;i<=m;i++)
    19 for(int j=1;j<=i;j++)
    20 cin>>a[i][j];
    21 memset(dp,0,sizeof(dp));
    22 for(int i=1;i<=m;i++)
    23 for(int j=1;j<=i;j++)
    24 dp[i][j]=a[i][j]+max(dp[i-1][j-1],dp[i-1][j]);//记录每一层的最大值; 
    25 for(int j=1;j<=m;j++)
    26 ans=max(ans,dp[m][j]);//比较最低一层的最大数据; 
    27 cout<<ans<<endl;
    28 }
    29 }
    30 return 0;
    31 }

    2:最长增序列

    题目:百练 2757.

    解题思想:记录每个数之前的最大增序列,最后遍历一遍记录数据,得到最大增序列长度;(难度略稍于数塔之后,属于简单的背包问题);

    代码如下:

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int max(int a,int b)
     5 {
     6 return a>b?a:b;
     7 }
     8 
     9 int main()
    10 {
    11 int n;//数组长度; 
    12 while(cin>>n)
    13 {
    14 int dp[35],a[35],ans=0; 
    15 for(int i=1;i<=n;i++)
    16 cin>>a[i];
    17 memset(dp,0,sizeof(dp));
    18 for(int i=1;i<=n;i++)//遍历到第i个数; 
    19 for(int j=1;j<=i;j++)//遍历第一个数到到这第i个数; 
    20 if(a[i]>a[j]) 
    21 dp[i]=max(dp[j]+1,dp[i]);// 不断更新第i个数之前的最长增序列有多少个 ;
    22 for(int i=1;i<=n;i++) 
    23 ans=max(dp[i],ans);//最后遍历一遍记录数据; 
    24 cout<<ans+1<<endl;
    25 }
    26 return 0;
    27 }

    /*

    举个例子好理解:

    8

    3 7 1 8 2 5 6 9

    第一个数是3;3之前没有比3小的数,所以dp[1]=0;第二个数是7;之前有比它小的3,所以dp[2]=1;接着dp[3]=0;到dp[4]时,遍历dp[1]时,因为满足8>3,暂时dp[4]更新为1;遍历到dp[2]时,因为8>7,此时dp[2](为2)>当时dp[4](为1)所以,dp[4]更新为2;再遍历dp[3]时,虽然8>1,但此时dp[4]>dp[3],所以dp[4]保留原值2......一直到9时,dp[8]更新为4;最后遍历一遍dp[1]-dp[8]:0,1,0,2,1,2,3,4得到dp[8]最大,所以最长增序列为dp[8]+1=5(加9本身);

    */

    3.01背包问题

    题目:HDU 2546(一类题)

    解题思想:01背包就是拿与不拿的问题;当给定一个背包容器,各物体重量和价值时,我们就一个一个来试试,并把我们试的数据储存下来(试的时候用到了辅助背包,就是重量为1到背包最大重量的背包,怎么用等下讲),方便下一次试的时候在已有的数据里拿出最大的那组数据;(就是解决子问题嘛,为方便回忆,等下列出01背包表并详细解释表格的数据代表什么,便于灵活运用)

    代码如下:

     1 #include<iostream> 
     2 #include<cstring>
     3 using namespace std;
     4 int max(int a,int b)
     5 {
     6     return a>b?a:b;
     7 }
     8 
     9 int main()
    10 {
    11     int num,maxspace;//num代表背包个数,maxspace代表背包最大容量 
    12     while(cin>>num>>maxspace)
    13     {
    14         int weight[10],value[10],dp[11][100];//weight为每个背包重量,value为每个背包价值 
    15         for(int i=1;i<=num;i++)
    16         cin>>weight[i];
    17         for(int i=1;i<=num;i++)
    18         cin>>value[i];
    19         memset(dp,0,sizeof(dp));
    20         for(int i=1;i<=num;i++)//尝试第i个背包 
    21         for(int j=1;j<=maxspace;j++)//重量为1到maxspace重的背包来尝试第i个背包 
    22         if(j>=weight[i])//如果承重为j的背包可以放 
    23         dp[i][j]=max(value[i]+dp[i-1][j-weight[i]],dp[i-1][j]);//放入i的价值加上之前以记录承重为j-weight[i] 的最大价值和没加的i-1物体承重为j的最大价值;(绕口) 
    24         else
    25         dp[i][j]=dp[i-1][j];//如果放不下则直接保存i-1物体承重为j的最大价值;(好像不用else也行,因为放不进去的数据不会用到) 
    26         cout<<dp[num][maxspace]<<endl;//dp[num][maxspace]肯定为最大值,等下看表一目了然; 
    27         //以下为打表
    28         for(int i=1;i<=num;i++)
    29         {
    30             for(int j=1;j<=maxspace;j++)
    31                 cout<<dp[i][j]<<"	";
    32             cout<<endl; 
    33         }
    34     }
    35     return 0;
    36 }

    /*

    依然举例说明:

    先说dp[i][j]代表面对前i件物品,辅助背包容量为j时,所取得的最大价值。

    5个物品,背包承重为10;5行从上往下为面对第i个物体,10列为重量1-10的辅助背包;

    先看第一行第一列dp[1][1];因为中量为1的辅助背包不能放下质量为2的第一个物品,所以最大价值为0,之后辅助背包大于等于二后能放,于是dp[1][1]-dp[1][10]都为4;再面对第2个物品,主要看dp[2][3]和dp[2][4];dp[2][3]表示只放了2,而dp[2][4]则为放了4;又在dp[2][6]时的10是因为辅助背包为6时,6>4;可以放入,但值得注意的是,试空间为6的背包时就用到了dp[2-1][6-4]即dp[1][2]时的数据,此时表示刚好放入我就放,我们知道,在此之前的数据都是最大的,此时得出的数据就也是最大的,之后依此类推;再看dp[3][3]辅助背包承重为3时,可以放物体1或3;但物体3的价值大于物体一的价值,于是最大数据就被更新了,总之在得出最大数据时,我们在不断更新最大数据,得出的答案便在最后一个(最后一个数据时从之前的数据得来的)。

    差不多就这样吧,表达能力有限,自己懂就行,其他人,随缘吧。

    */

  • 相关阅读:
    UVA 10617 Again Palindrome
    UVA 10154 Weights and Measures
    UVA 10201 Adventures in Moving Part IV
    UVA 10313 Pay the Price
    UVA 10271 Chopsticks
    Restore DB後設置指引 for maximo
    每行SQL語句加go換行
    种服务器角色所拥有的权限
    Framework X support IPV6?
    模擬DeadLock
  • 原文地址:https://www.cnblogs.com/wwq-19990526/p/8606708.html
Copyright © 2011-2022 走看看