【暑假集训】之被ACM金牌大神虐的第一天之dp篇(未完结)

【感想1】终于到7.31了,终于见到传说中的ACM金牌的大神了,终于要讲课了,好激动!!!然而听了一上午,彻底被虐成翔了。。QAQ再见再见
第一题:
酱神寻宝(CDOJ1141)
酱神来到了一座小岛,岛上有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

3
1 0 0 0 1
2 4 0 8 0
3 9 10 9 8
3 1 2

Sample Output

8

思路:

首先有一个贪心策略,就是能用金银钥匙就不用万能钥匙,那么就可以将此应用于dp之间,此题可用状压dp做,我们设一个st来保存每个箱子的状态,对于每个st,我们可以计算出手里的钥匙总数,也就是说,在总数一定的情况下,我们要希望万能钥匙的数量尽可能的多,那么我们就设定一个状态,我们设dp[st][i]为当箱子状态为st时,手里金钥匙为i把时,万能钥匙的总数最多能有多少把(由于总数是确定的,我们知道金钥匙,万能钥匙的总数,银钥匙自然也能计算出),我们转移的时候枚举一个当前没有打开的箱子,在优先使用金银钥匙的情况下,实在不行再用万能钥匙,这样来转移方程。

额,由于时间限制,先只写思路,代码未实现,把思路记下,找时间来实现。


传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=154402

Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u

 Status

Description

Alice is playing a game with JSL. (...where is Bob?) 


Alice picks a number   from segment  . After saw this number, JSL picks a number   from segment  .(  and   may have same value). Finally, they compute   (  is exclusive or). Alice wants   to be as maximal as possible while JSL wants   to be as minimal as possible. Alice and JSL are both clever enough, and what's the final value of  ?
 

Input

Multiple test cases. In the first line there is an integer  , indicating the number of test cases. 
For each test cases, there are four integers   . 
 

Output

For each test case, output one line. The output format is Case #x: ans, x is the case number,starting from   is the value of  .
 

Sample Input

       
       
2 1 4 3 8 1 3 4 7
 

Sample Output

       
       
Case #1: 2 Case #2: 4
 

【中文题意】:
Alice从[l1,r1]中选出一个数字x,JSL看到这个数字之后从[l2,r2]中取出一个数字y(y可能和x相同)。最后他们计算出数字z=x⊕y(⊕为异或运算)。Alice希望z尽可能大,而JSL希望z尽可能小。Alice和JSL都 很聪明,那么z最后会是多少


【感想2】这道题依旧很虐心啊。。。记得我当时听讲时,随手搜了一下题解,发现了一个人写了130多行的if else,并且强烈吐槽了出这道丧病的题的人,而今天,出这道丧病的题的人就在我们面前给我们讲着这道题,话说这道题的dp状态也是丧心病狂啊。。。废话不多说,开写思路
【思路】:
大神是这样开导我们的:首先,如果l1,r1,l2,r2,的范围都是1000,那该怎么做?那么我们便枚举x,y,内层循环取min,外层循环取max,好,那么我们继续扩大范围,如果都是10^9该怎么做呢,首先枚举肯定没戏!!那么我们来换一下想法,首先操作是一个异或操作,那我们便往二进制方面想,由于两人都clever enough,那么就有一个贪心的策略,从高位向低位贪心,就是双方在博弈谁可以获得最高位的价值,那好,我们的方向便是这里,这里便有一个上界,下界 的问题,因为有可能y的最高位达不到x最高位。双方在选择数字时都会有一个上界,下界l,r。 但是如果在一个下界为0的地方填了1,那么后面的下界就全为0了
举例:
x >= 11010111
x == 101.....
那么x >= 10100000
那么, 同理我们可以推出上界的变化。我们发现上下界只有两种选法。
1、要么是原来的上下界
2、要么是全0或全1
于是丧心病狂的dp状态来了,我们定义dp[i][l1][r1][l2][r2](OMG五维数组。。)表示考虑后i位,l,r都用0,1表示的两人边界的情况,dp值便是最后的价值,状态出来了,我们来考虑丧心病狂的状态转移吧:
现在我们考虑转移,因为是Alice先选,我们先考虑她的决策。即她在第i位选择填0或者填1,如果Alice的上下界对应的这位都是0或者都是1,那么她没有选择的余地,如果上下界是1-0( 注意:没有0-1),那么她可以选0,可以选1,这是就来dp决策,如果Alice选过了,我们考虑JSL去选择,那么JSL一定想选择一个和Alice选的一样的数字。因为这样这一位异或起来就是0。同样考虑JSL的上下界情况。如果这一位一样那么只能填某个数字。否则一定会填一个和Alice选的数字一样的数。这就是这个丧心病狂的题的丧病的思路,据出这道题的大神讲,这个思路就算l,r的范围是10^18次方也不怕!! 得意 微笑,然而还是没时间实现代码。。。


酱神的旅行(CDOJ1140)

酱神要去一棵树上旅行。
酱神制定了一个旅行计划,他要按顺序去m个树上的结点,a1,a2,a3,...,am。
酱神有一辆车,树上的每一条边既可以开车通过,也可以走过去,两种方法需要不同的时间。如果选择走路,酱神需要先把车停在结点上,在他下一次要开车的时候,必须先回到停车的结点取车。
酱神和他的爱车一开始都在a1结点上,酱神要依次访问完这m个结点最少需要多少时间
【感想3】WTF!!shen me gui!!这道题我百度居然没百度到!!唉,dp虐我千百遍,我待dp如初恋。。 这道题,我觉得比起上一道题算比较简单了(注:与上一题比较)
【思路】:
把酱神走的路径暴力求出来。最多n*m。并把路径上的节点依次编号。在最终的路径上去DP,这是大神给的思路,也是。。醉了,
我们不能单纯的设dp[i]为在路径的i点上的最大值,因为有走路和坐车,所以:
•dp[i][0]表示酱神在路径的第i个点上且他身边没有车时他所需要的最小时间
•dp[i][1]表示有车
•dp[0][0]=inf
•dp[0][1]=0
状态转移:
dp[i][0]=min(dp[i-1][0],dp[i-1][1])+cost_walk 
// 既然没有车,那么只能走过来
有车的时候有两种情况。
1、从第i-1个点开车到第i个点。
2、从第i-1个点走到第i个点,在第i个点捡到原来停    在这里的车。
第一种情况很简单:
dp[i][1]=dp[i-1][1]+cost_car
对于第二种,我们也要快速的进行dp:
不妨设当前点为u,u之前还在路径的第j1,j2,..jm个点上出现了。j1,j2,...jm<i
•dp[i][1]=min(dp[jk][1]+walk_from_jk_to_i)
•(1=<k<=m)
这个方程的意义就是原来把车停在jk这个点上,然后回到jk这个点捡原来的车。
如何快速计算walk_from_jk_to_i。
这是连续的一段,可以维护走路代价的前缀和sum
//这里有点没看懂啊,这里直接引用金牌大神的题解
不妨用sum数组表示前缀和。
dp[i][1]=min(dp[i][jk]+sum[i]-sum[jk-1])
dp[i][1]=min(dp[i][jk]-sum[jk-1])+sum[i]
看上去还要枚举jk,其实所有的有个共同的性质,这些点对应到树上都是同一个点!
令 f[u]=min(dp[jk][1]-sum[jk-1]) a[jk]=u,jk<i
先用f更新dp
dp[i][1]=min(dp[i-1][1]+cost_car,f[u]+sum[i])
再用dp更新f
f[u]=min(f[u],dp[i][1]-sum[i-1])





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值