zoukankan      html  css  js  c++  java
  • 洛谷P1064金明的预算方案(好题难题,依赖的背包dp,或计算拓扑先后顺序+记忆化搜索)

    题目链接:https://www.luogu.org/problemnew/show/P1064

    这里不讲dp,只讲搜索记忆化。这题看到时比较难,无从入手,但想通后就和上一题开心的金明一样了,只不过搜索时由2选择方向变成了5个选择方向而已,其他基本不变。

    .刚开始想直接在上一题记忆化的代码上修改一下就交了,但一直WA,多了附件,状态没法存啊。。。想了好长时间,直到发现大佬的这段话:

    这个题的决策是五个,分别是:

    1.不选,然后去考虑下一个

    2.选且只选这个主件

    3.选这个主件,并且选附件1

    4.选这个主件,并且选附件2

    5.选这个主件,并且选附件1和附件2.

    这个。。。很好想吧。。。

    顿时恍然大悟,没法直接存状态,就先拓扑计算出先后顺序啊,然后就只是增加方向,和上一题一样了!(另外,在排序时有个下标混乱的bug坑点要注意,代码有注释)

    先上一份原来的基础记忆化搜索,本题的搜索就是在此基础上改的

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <cmath>
     7 using namespace std;
     8 const int maxn=1e5+5;
     9 int v[maxn],w[maxn],ji[maxn];
    10 int f[30][100005];
    11 int n,m;
    12 
    13 int so(int step,int sumv)
    14 {
    15     if(f[step][sumv]) return f[step][sumv];
    16     if(step==m+1) return 0;
    17 
    18     int ans=0,ls=0,rs=0;
    19     if(sumv+v[step]<=n) { ls=ls+ji[step]+so(step+1,sumv+v[step]); }
    20     if(sumv<=n) rs=rs+so(step+1,sumv);
    21 
    22     ans=max(ls,rs);
    23     return f[step][sumv]=ans;
    24 }
    25 
    26 int main()
    27 {
    28     cin>>n>>m;
    29     for(int i=1;i<=m;i++)
    30     {
    31         cin>>v[i];
    32         cin>>w[i];
    33         ji[i]=v[i]*w[i];
    34     }
    35 
    36     int ans=so(1,0);
    37 
    38     cout<<ans<<endl;
    39 
    40     return 0;
    41 }

    本题对上基础搜索修改:

      1 #include <iostream>
      2 #include <string>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <cstdio>
      6 #include <cstring>
      7 using namespace std;
      8 typedef long long ll;
      9 const int maxn=1e6+5;
     10 int f[65][32005];
     11 int n,m;
     12 struct px
     13 {
     14     int v;
     15     int ji;
     16     int w;
     17     int q;
     18     int ii;//记录原来下标,排序后要用到很关键!
     19 }T[maxn];
     20 bool cmp(px aa,px bb)
     21 {
     22     return aa.q<bb.q;
     23 }
     24 vector<px> vec[maxn];
     25 
     26 
     27 int so(int step,int sumv)
     28 {
     29     //只递归主件,附件直接跳过
     30     if(f[step][sumv]!=-1) return f[step][sumv];
     31     if(step==m+1) return 0;
     32 
     33     int ans=0,l1=0,l2=0,l3=0,l4=0,l5=0;
     34 
     35     if(sumv<=n) l1+=+so(step+1,sumv);
     36     if(sumv+T[step].v<=n) { l2+=T[step].ji+so(step+1,sumv+T[step].v); }
     37     int I=T[step].ii;
     38     int len=vec[I].size();
     39     if(len>=1 && sumv+vec[I][0].v<=n) { l3+=vec[I][0].ji+so(step+1,sumv+vec[I][0].v); }
     40     if(len>=2 && sumv+vec[I][1].v<=n) { l4+=vec[I][1].ji+so(step+1,sumv+vec[I][1].v); }
     41     if(len>=3 && sumv+vec[I][2].v<=n) { l5+=vec[I][2].ji+so(step+1,sumv+vec[I][2].v); }
     42 
     43     ans=max(ans,l1);
     44     ans=max(ans,l2);
     45     ans=max(ans,l3);
     46     ans=max(ans,l4);
     47     ans=max(ans,l5);
     48     return f[step][sumv]=ans;
     49 }
     50 
     51 int main()
     52 {
     53     ios::sync_with_stdio(false); cin.tie(0);
     54 
     55     cin>>n>>m;
     56     for(int i=1;i<=m;i++)//1.输入
     57     {
     58         cin>>T[i].v>>T[i].w>>T[i].q;
     59 
     60         T[i].ji=T[i].v*T[i].w;
     61         T[i].ii=i;
     62         if(T[i].q>0)//可以的话存入附件1,2
     63         {
     64             int x=T[i].q;
     65 
     66             if(T[x].v+T[i].v<=n)
     67             {
     68                 px t;
     69                 t.v=T[x].v+T[i].v;
     70                 t.ji=T[x].ji+T[i].ji;
     71                 vec[x].push_back(t);
     72             }
     73         }
     74     }
     75 
     76     for(int i=0;i<=m+1;i++)//2.记忆数组初始化
     77     {
     78         for(int j=0;j<=n+1;j++)
     79         {
     80             f[i][j]=-1;
     81         }
     82     }
     83 
     84     sort(T+1,T+1+m,cmp);//3.排序,去掉附件,只留主件(这一点很容错是隐藏的bug错误不然前面必错,找了好长时间的bug,QAQ~~~)
     85     for(int i=1;i<=m;i++)//等等,好像还不能排序...一排原来存好的vector下标就乱了对不上了!!
     86     {                    //所以,关键是这,结构体中用一个变量ii存下原来的属于自己的下标,这样排序后还能记录原来下标
     87         if(T[i].q>0)
     88         {
     89             m=i-1;
     90             break;
     91         }
     92     }
     93 
     94     for(int i=1;i<=m;i++)//4.试试能不能2附件同时取,存入这种情况
     95     {
     96         int I=T[i].ii;
     97         int len=vec[I].size();
     98         if(len>=2)
     99         {
    100             int v1=vec[I][0].v-T[i].v;
    101             int ji1=vec[I][0].ji-T[i].ji;
    102             int v2=vec[I][1].v-T[i].v;
    103             int ji2=vec[I][1].ji-T[i].ji;
    104 
    105             if(T[i].v+v1+v2<=n)
    106             {
    107                 px t;
    108                 t.v=T[i].v+v1+v2;
    109                 t.ji=T[i].ji+ji1+ji2;
    110                 vec[I].push_back(t);
    111             }
    112         }
    113     }
    114 
    115     /*cout<<endl;//输出准备工作做完的序列,便于查找错误,你只要排好了按照上一题的记忆化搜索就一定没错!
    116     for(int i=1;i<=m;i++)
    117     {
    118         cout<<T[i].v<<' '<<T[i].ji<<' '<<T[i].ii<<endl;
    119         int I=T[i].ii;
    120         for(int j=0;j<vec[I].size();j++)
    121         {
    122             cout<<vec[I][j].v<<' '<<vec[I][j].ji<<endl;
    123         }
    124     }*/
    125 
    126     int ans=so(1,0);
    127     cout<<ans<<endl;
    128 
    129     return 0;
    130 }

    完。

  • 相关阅读:
    MYSQL关于数据库的操作命令
    理解js中的原型和原型链
    float引起的高度塌陷问题
    使用webpack2.0 搭建前端项目
    jquery插件开发总结
    js中的OOP编程
    关于gulp的基本使用
    关于requireJs的学习总结
    vuex的学习总结
    事件中的target与currentTarget的区别
  • 原文地址:https://www.cnblogs.com/redblackk/p/9904763.html
Copyright © 2011-2022 走看看