zoukankan      html  css  js  c++  java
  • DP(1) 背包

    01背包模型

    1 for (int i=1;i<=n;i++)
    2   for (int j=1;j<=Max_c;j++)
    3     f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+value[i]);
    01背包 转移方程

    1.[noip2005pj]采药

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 
     6 int time[105],value[105],f[105][1005];
     7 
     8 int main()
     9 {
    10     int maxtime,tot;
    11     scanf("%d%d",&maxtime,&tot);
    12     for (int i=1;i<=tot;i++)
    13       scanf("%d%d",&time[i],&value[i]);
    14     
    15     memset(f,0,sizeof(f));
    16     for (int i=1;i<=tot;i++)
    17       for (int j=1;j<=maxtime;j++)
    18       {
    19           f[i][j]=f[i-1][j];
    20           if (j>=time[i])
    21             f[i][j]=max(f[i][j],f[i-1][j-time[i]]+value[i]);
    22       }
    23       
    24     printf("%d",f[tot][maxtime]);
    25     return 0;
    26 }
    View Code

    2.[vijos1037]搭建双塔

    题意:在n个数中选取若干个求和,得到两个相等的数,求最大数

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 
     6 bool f[100][2005][2005];
     7 int h[105];
     8 int main()
     9 {
    10     int n;
    11     scanf("%d",&n);
    12     memset(h,0,sizeof(h));
    13     int tot=0;
    14     for (int i=1;i<=n;i++){
    15       scanf("%d",&h[i]);
    16       tot+=h[i];
    17     }
    18     tot/=2;
    19     tot++;
    20     memset(f,0,sizeof(f));
    21     f[0][0][0]=1;
    22     for (int i=1;i<=n;i++)
    23       for (int j=0;j<=tot;j++)
    24         for (int k=0;k<=tot;k++){
    25           f[i][j][k]=f[i-1][j][k];
    26           if (j>=h[i]) f[i][j][k]=f[i][j][k]||f[i-1][j-h[i]][k];
    27           if (k>=h[i]) f[i][j][k]=f[i][j][k]||f[i-1][j][k-h[i]];
    28     }
    29     int num=tot;
    30     while (num>0) 
    31     {
    32         if (f[n][num][num]==1) break;
    33         num--;
    34     } 
    35     if (num!=0) printf("%d
    ",num);
    36     else printf("Impossible");
    37     return 0;
    38 }
    RE一个点

    f[i][j]表示前i块水晶,两塔高度差为j时,较低塔的高度

    目标状态为f[n][0]

    则对于h[i]需考虑四种情况:(可画图帮助理解)

    1)不取 f[i][j]=f[i-1][j]

    2)放在较低塔上,仍是较低的 f[i][j]=max(f[i][j],f[i-1][j+h[i]]+h[i])

    3)放在较低塔上,变成较高的 f[i][j]=max(f[i][j],f[i-1][h[i]-j]+h[i]-j)

    4)放在较高塔上  f[i][j]=max(f[i][j],f[i-1][j-h[i]])

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    
    int f[105][2005],h[105];
    int main(){
        int n,tot=0;
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
          scanf("%d",&h[i]);
          tot+=h[i];
        }
        memset(f,-1,sizeof(f));
        f[0][0]=0;
        for (int i=1;i<=n;i++)
            for (int j=0;j<=tot;j++){
                if (f[i-1][j]!=-1) f[i][j]=f[i-1][j];
                if (f[i-1][j+h[i]]!=-1) f[i][j]=max(f[i][j],f[i-1][j+h[i]]+h[i]);
                if (j>=h[i]&&f[i-1][j+h[i]!=-1]) f[i][j]=max(f[i][j],f[i-1][j-h[i]]);
                if (h[i]>=j&&f[i-1][h[i]-j]!=-1) f[i][j]=max(f[i][j],f[i-1][h[i]-j]+h[i]-j);
            }
        int num=tot;
        if (f[n][0]>0) printf("%d",f[n][0]);
        else printf("Impossible");
        return 0;
    }
    AC

    3.[noip2007tg] 金明的预算方案

    有依赖的背包

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    
    int price[65],imp[65];
    int infor[60][4];
    int f[60][3500];
    
    //预处理:a.主件,附件
    //           b.数字除以10
    int main(){
        int n,m,a,b,c;
        memset(infor,0,sizeof(infor));
        scanf("%d%d",&n,&m);
        n/=10;
        for (int i=1;i<=m;i++){
            scanf("%d%d%d",&price[i],&imp[i],&c);
            price[i]/=10;
            imp[i]*=price[i];
            if (c==0) infor[i][0]=1;
            else{//是附件
              infor[i][0]=0;
              infor[c][3]++;
              infor[c][infor[c][3]]=i;
            }
        }
        int Last=0;
        memset(f,0,sizeof(f));
        for (int i=1;i<=m;i++){
            if (infor[i][0]==0) continue;
            for (int j=0;j<=n;j++){
                 f[i][j]=f[Last][j];
                //不取主件 
                 if (j>=price[i]) f[i][j]=max(f[i][j],f[Last][j-price[i]]+imp[i]);
                //只取主件 
                 if (infor[i][3]>0&&j>=price[i]+price[infor[i][1]])
                   f[i][j]=max(f[i][j],f[Last][j-price[i]-price[infor[i][1]]]+imp[i]+imp[infor[i][1]]);
                 //取主件和第一件附件  
                 if (infor[i][3]==2&&j>=price[i]+price[infor[i][2]])
                   f[i][j]=max(f[i][j],f[Last][j-price[i]-price[infor[i][2]]]+imp[i]+imp[infor[i][2]]);
                //取主件和第二件附件
                if (infor[i][3]==2&&j>=price[i]+price[infor[i][1]]+price[infor[i][2]])
                   f[i][j]=max(f[i][j],f[Last][j-price[i]-price[infor[i][1]]-price[infor[i][2]]]+imp[i]+imp[infor[i][1]]+imp[infor[i][2]]);     
                 //取主件和两件附件  
            }
            Last=i;
        }
        printf("%d",f[Last][n]*10);
        return 0; 
    } 
    View Code

    总结:注意考虑到多种情况,还有各种小技巧的使用

  • 相关阅读:
    修改apache的默认访问目录
    禁止浏览器直接访问php文件
    使用Apache Bench进行压力测试
    关于mysql(或MariaDB)中的用户账号格式
    单表查询
    CSS设计指南之一 HTML标记与文档结构
    SQL SERVER技术内幕之10 可编程对象
    SQL SERVER技术内幕之10 事务并发
    观察者模式
    中介者模式
  • 原文地址:https://www.cnblogs.com/vincent-hwh/p/6043619.html
Copyright © 2011-2022 走看看