zoukankan      html  css  js  c++  java
  • ACM-ICPC(9/26)

    DP专题

    • 多阶段决策:递推——逆推方式(难度较大),记忆化搜索方式,考虑当前决策层(cur)

    • 01背包:变形众多,两种方式,一是考虑阶段的方式, ,另一种是刷表法

    题目推荐:

    bzoj 4247

    Description

    JOI君有N个装在手机上的挂饰,编号为1...N。 JOI君可以将其中的一些装在手机上。

    JOI君的挂饰有一些与众不同——其中的一些挂饰附有可以挂其他挂件的挂钩。每个挂件要么直接挂在手机上,要么挂在其他挂件的挂钩上。直接挂在手机上的挂件最多有1个。

    此外,每个挂件有一个安装时会获得的喜悦值,用一个整数来表示。如果JOI君很讨厌某个挂饰,那么这个挂饰的喜悦值就是一个负数。

    JOI君想要最大化所有挂饰的喜悦值之和。注意不必要将所有的挂钩都挂上挂饰,而且一个都不挂也是可以的。

    Input

    第一行一个整数N,代表挂饰的个数。

    接下来N行,第i行(1<=i<=N)有两个空格分隔的整数Ai和Bi,表示挂饰i有Ai个挂钩,安装后会获得Bi的喜悦值。

    Output

    输出一行一个整数,表示手机上连接的挂饰总和的最大值

    Sample Input

    50 42 -21 -10 10 3

    Sample Output

    5

    HINT

    将挂饰2直接挂在手机上,然后将挂饰1和挂饰5分别挂在挂饰2的两个挂钩上,可以获得最大喜悦值4-2+3=5。

    1<=N<=2000

    0<=Ai<=N(1<=i<=N)

    -106<=Bi<=106(1<=i<=N)

    分析:单纯考虑第一个挂饰,决策的顺序有很大的影响,这样会陷入暴力的方案中去,按照挂钩排序,这样就貌似不用考虑是否没有地方放了。考虑前 i 个物品, 是否能转移呢? 加一维 j 当前有多少挂钩,

    保证 j >=1 ,初始化状态 其他 负很多,这样才能将开始就是负数的状态转移上来。

    可以发现,这个过程其实就是一个01背包刷表过程。


    /**************************************************************
       Problem: 4247
       User: TreeDream
       Language: C++
       Result: Accepted
       Time:2180 ms
       Memory:17012 kb
    ****************************************************************/

    #include <bits/stdc++.h>

    using namespace std;

    const int inf =0x3f3f3f3f;

    int n;
    struct Node {
       int a,b;
       bool operator < (const Node& rhs) const {
           return a > rhs.a;
      }
    }nodes[2005];

    int dp[2005][2005];

    int main()
    {
       //freopen("in.txt","r",stdin);
       scanf("%d",&n);

       for(int i = 1; i <=n; i++)
           scanf("%d%d",&nodes[i].a,&nodes[i].b);
       sort(nodes+1,nodes+1+n);
       for(int i = 0; i <=n; i++)
           memset(dp[i],-inf,sizeof(dp[i]));

       dp[0][1] = 0;
       for(int i=1;i<=n;i++) {
           for(int j=n;j>=0;j--) {
               int tmp = max(j-nodes[i].a,0);
               dp[i][j] = max(dp[i-1][j],dp[i-1][tmp+1]+nodes[i].b);
          }
      }

       int ans = 0;
       for(int i = 0; i <= n; i++)
           ans = max(ans,dp[n][i]);
       printf("%d ",ans);

       return 0;
    }

    其实还有一些题目要推荐的:今天上课太热了,脑子有点晕,明天更新这一块的有趣的内容。

     

  • 相关阅读:
    一个从MongoDB中导出给定日期范围内数据的shell脚本
    Populate A List Item With Record Group In Oracle Forms Using Populate_List And Create_Group_From_Query Command
    An Example Of Validating Text Item In Oracle Forms Using When-Validate-Item Trigger
    Know How To Use ID_NULL Function To Search An Object In Oracle Forms
    Create XO Checker Game With Oracle Forms
    Using SYSTEM.MOUSE_ITEM In Oracle Forms
    Highlighting Text Item On Entry In Oracle Forms
    How To Tune or Test PLSQL Code Performance in Oracle D2k Forms
    Creating Timer in Oracle D2k / Forms 6i and Displaying a Clock
    Create Timer Example To Show Image Presentation in Oracle Forms
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7599592.html
Copyright © 2011-2022 走看看