zoukankan      html  css  js  c++  java
  • DP 简单题目练习

    ZOJ 1234

    这道题目我表示也还不是特别能理解。。。。还是太菜了T T

    从后往前思考,因为只要后面有多的数在,那么C肯定是存在的,只要考虑是否把前两个数加在一起作为badness值这样两种情况来考虑

    如果总数和3*j相同的话,那必然不用多考虑,它只能以前两个数的平方差作为badness值

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 
     6 int len[5005],dp[5005][1010];
     7 
     8 int main()
     9 {
    10     int T,k,n;
    11     scanf("%d",&T);
    12     while(T--){
    13         scanf("%d%d",&k,&n);
    14 
    15         memset(dp,0x3f,sizeof(dp));
    16         for(int i=0;i<=n;i++)
    17             dp[i][0]=0;
    18 
    19         k+=8;
    20         for(int i=1;i<=n;i++)
    21             scanf("%d",len+i);
    22     //i表示从i这点开始一直取到末尾,j表示取的筷子组
    23         for(int i=n-2;i>=0;i--){
    24             for(int j=1;j<=k&&n-i+1>=3*j;j++){
    25                 if(n-i+1 == 3*j)
    26                     dp[i][j] = dp[i+2][j-1] + (len[i]-len[i+1])*(len[i]-len[i+1]);
    27 
    28                 else if(n-i+1>3*j)
    29                    //这个语句表示对于最前面的那个数选不选取有两种可能性,不选,选了那么必然还要选取相邻的数和它作为一组
    30                     dp[i][j] = min(dp[i+1][j],dp[i+2][j-1] + (len[i]-len[i+1])*(len[i]-len[i+1]));
    31             }
    32         }
    33 
    34         printf("%d
    ",dp[1][k]);
    35     }
    36     return 0;
    37 }
    38     

    ZOJ 1366

    这道题目对于一种产品来说数量有多样,但我们直接用0-1背包做是会超时的,所以先把商品打包在一起,数量由1,2,4,8,16~这样叠加上去,也就是说,即使有1000个数量,也只需要数组用11个地址来保存即可。

    再根据0-1背包求解,这里最好把dp[]数组设为1元的,dp过程就逆向思考,不然二元的太耗内存,会不会爆我也没试过

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int cnt;//表示产品的量
     6 int price[120],dp[100005];
     7 
     8 //多重背包转化成0-1背包来求解
     9 void change(int k,int pri)
    10 {
    11     int a=1;
    12     price[0]=0;
    13     while(k>a){
    14         price[++cnt] = a*pri;
    15         k-=a;
    16         a<<=1;
    17     }
    18     price[++cnt] = k*pri;
    19 }
    20 
    21 int main()
    22 {
    23     int cash,n,d,pri;
    24 
    25     while(~scanf("%d%d",&cash,&n)){
    26         cnt=0;
    27         memset(dp,0,sizeof(dp));
    28 
    29         for(int i=0;i<n;i++)
    30         {
    31             scanf("%d%d",&d,&pri);
    32             change(d,pri);
    33         }
    34 
    35         for(int i=1;i<=cnt;i++){
    36             for(int j=cash;j>=1;j--){
    37                 if(j>=price[i])
    38                     dp[j] = max(dp[j],dp[j-price[i]]+price[i]);
    39             }
    40         }
    41 
    42         printf("%d
    ",dp[cash]);
    43     }
    44     return 0;
    45 }
  • 相关阅读:
    C# 操作ACCESS数据库
    装饰模式(Decorator Pattern)
    桥接模式(Bridge Pattern)
    单件模式(Singleton Pattern)
    横竖不能重复的9个数,,,,,
    C#操作Access数据库的例子
    组合模式(Composite Pattern)
    建造者模式(Builder Pattern)
    工厂方法模式(Factory Method)
    外观模式(Façade Pattern)
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4001903.html
Copyright © 2011-2022 走看看