UESTC_酱神寻宝 2015 UESTC Training for Dynamic Programming<Problem O>

O - 酱神寻宝

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

酱神来到了一座小岛,岛上有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\n",ans);
  return 0;
}

 

转载于:https://www.cnblogs.com/Xiper/p/4539658.html

互联网络程序设计是指在互联网上进行程序开发和设计的过程。UESTC则是我国的一所著名高校——电子科技大学。 互联网络程序设计 uestc包含了两个主要的方面:互联网络和程序设计。互联网络是指将多个计算机网络通过通信链路互相连接起来,实现信息共享和资源共享的网络系统。程序设计是指根据需求和目标,通过编写代码和设计算法,实现计算机程序的过程。 互联网络程序设计 uestc的学习内容主要包括以下几个方面: 1. 网络知识:学习互联网络的基本概念、原理和协议,如TCP/IP协议、HTTP协议等。掌握网络编程的基本技术,能够编写网络应用程序。 2. 数据通信:学习数据通信的基本原理和技术,包括数据传输的方式、数据压缩和加密等。了解网络安全和数据保护的基本知识。 3. 程序设计:学习编程语言和开发工具,如Java、C++和Python等。掌握常用的编程技巧和方法,能够设计和实现复杂的网络应用程序。 4. Web开发:学习Web开发的基本知识和技术,包括HTML、CSS、JavaScript等。能够设计和实现交互式的Web应用程序。 5. 数据库技术:学习数据库的基本原理和技术,如SQL语言和数据库管理系统。能够设计和管理数据库,实现数据的存储和检索。 通过学习互联网络程序设计 uestc,可以掌握互联网应用开发的基本技能,具备设计和实现网络应用程序的能力。这对于目前互联网行业的人才需求来说是非常重要的,也为学生提供了广阔的就业和创业机会。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值