zoukankan      html  css  js  c++  java
  • UESTC_酱神寻宝 2015 UESTC Training for Dynamic Programming<Problem O>

    O - 酱神寻宝

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    酱神来到了一座小岛,岛上有n个箱子。

    一共有3中不同的钥匙,金钥匙、银钥匙和万能钥匙。酱神一开始有a把金钥匙、b把银钥匙和c把万能钥匙。

    i个箱子上有xi把金锁,yi把银锁。金钥匙只能打开金锁,银钥匙只能打开银锁,万能钥匙两种锁都能打开。用于打开锁的钥匙会立刻损坏,酱神会丢掉损坏的钥匙。箱子里有ai把金钥匙、bi把银钥匙和ci把万能钥匙,想要取出箱内的钥匙必须要打开这xi+yi把锁。

    酱神的目的是使他拥有的钥匙总数最多。一旦酱神认为自己已经拥有了最多的钥匙,他就不会去开剩下的箱子了。

    Input

    第一行一个数n

    接下来有n行。每行5个数,xi,yi,ai,bi,ci

    最后一行3个数a,b,c

    1=<n<=15

    0=<xi,yi,ai,bi,ci,a,b,c<=10

    Output

    输出一个数酱神的最多钥匙数。

    Sample input and output

    Sample InputSample Output
    3
    1 0 0 0 1
    2 4 0 8 0
    3 9 10 9 8
    3 1 2
    
    8
    
    1
    0 0 1 2 3
    0 0 0
    
    6
    

    Hint

    第一个样例中酱神会打开第一个和第二个箱子。

    解题思路:

    首先贪心,能用金 / 银就不用万能钥匙.

    我们不妨令 f ( i , j ) -> 开启箱子的状态为 i , 金钥匙为 j 把时能获得最多的万能钥匙.

    之后我们考虑更新,设 0 为没开启过, 1 为开启过.

    每次更新都是由 x 个 0 的状态更新到 x+1 个 0 的状态.

    我们采用bfs维护这种顺序即可

    不过由于本题数据很水,各位可以尝试各种花式方法水过去!!

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    /*
     f( i , j ) - > 当前开的箱子的集合为 i , 金钥匙的数目是 j 时可以获得的最多万能钥匙数目. 
    */
    
    using namespace std;
    const int maxn = 15;
    int n,sta,stb,stc,f[1 << 15][ maxn*11 ],ans = 0;
    typedef struct Item
    {
       int needA,needB,getA,getB,getC;
    };
    
    
    typedef struct updatastatus
    {
       int st,number;    
       updatastatus(const int &st,const int &number)
       {
             this->st = st , this->number = number;
       }
    };
    
    
    bool arrived[1 << 15][maxn * 11];
    queue<updatastatus>q;
    Item A[maxn+3];
    
    inline void updata(int i,int j,int newans)
    {
        f[i][j] = max(f[i][j],newans);
    }
    
    //可以开启为 0 , 不能开启为 1; 
    
    int main(int argc,char *argv[])
    {
      scanf("%d",&n);
      for(int i = 0 ; i < n ; ++ i) scanf("%d%d%d%d%d",&A[i].needA,&A[i].needB,&A[i].getA,&A[i].getB,&A[i].getC);
      scanf("%d%d%d",&sta,&stb,&stc);
      f[0][sta] = stc; // Init;
      memset(arrived,false,sizeof(arrived));
      q.push(updatastatus(0,sta));
      while(!q.empty())
       {
             updatastatus ns = q.front();q.pop();
             int ra = ns.number, rb, rc = f[ns.st][ns.number] , all = sta + stb + stc , st = ns.st;
             for(int i = 0 ; i < n ; ++ i)
              if (ns.st >> i & 1)
               all += A[i].getA + A[i].getB + A[i].getC - A[i].needA - A[i].needB;
             ans = max(ans,all);
             rb = all - ra - rc;
             for(int i = 0 ; i < n ; ++ i)
              {
                    if (!(st >> i & 1))
                     {
                           int needA = A[i].needA;
                           int needB = A[i].needB;
                           int getA = A[i].getA;
                           int getB = A[i].getB;
                           int getC = A[i].getC;
                           if (ra >= needA) //金够 
                            {
                              if (rb >= needB) //金银都够
                               {
                                  updata(st | (1 << i) , ra - needA + getA, rc + getC);
                         if (!arrived[st | (1 << i)][ra - needA + getA])
                          {
                            q.push(updatastatus(st | (1 << i),ra - needA + getA));
                            arrived[st | (1 << i)][ra - needA + getA] = true;
                          }    
                       }
                     else  //金够银不够 
                      {
                           if (needB- rb <= rc)
                            {
                                  updata(st | (1 << i) , ra - needA + getA, rc - needB + rb + getC);
                                  if (!arrived[st | (1 << i)][ra - needA + getA])
                              {
                                q.push(updatastatus(st | (1 << i),ra - needA + getA));
                                arrived[st | (1 << i)][ra - needA + getA] = true;
                              }    
                          }
                      }
                   }
                  else
                   {
                        if (rb >= needB) //金不够银够 
                         {
                              if (needA - ra <= rc)
                            {
                                  updata(st | (1 << i) , getA, rc - needA + ra + getC);
                                  if (!arrived[st | (1 << i)][getA])
                              {
                                q.push(updatastatus(st | (1 << i),getA));
                                arrived[st | (1 << i)][getA] = true;
                              }    
                          }
                      }
                     else  //金不够银不够 
                      {
                           if (needA - ra + needB - rb <= rc)
                          {
                               updata(st | (1 << i) , getA, rc - needA + ra - needB + rb + getC);
                               if (!arrived[st | (1 << i)][getA])
                              {
                                q.push(updatastatus(st | (1 << i),getA));
                                arrived[st | (1 << i)][getA] = true;
                              }    
                          }      
                      } 
                   }
               }
           }
       }
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    【一】、Cypress下载及安装介绍
    利用Selenium多用户同时开启多线程登录博客园
    实用的jsonpath模块
    Linux常用命令
    Python读取CSV文件
    python算法集锦【四】
    基础类封装-浏览器文件上载类库封装
    基础类封装-查找页面元素类库封装
    基础类封装-键盘类操作库封装
    自动化测试框架Python+selenium+unittest系列 之 配置文件读取(Python)
  • 原文地址:https://www.cnblogs.com/Xiper/p/4539658.html
Copyright © 2011-2022 走看看