hdu 5208 Where is Bob

题意:

问题描述
Alice和JSL正在玩一个游戏(Bob呢?)。
Alice从
  
  
   
   [l1,r1]
  
  中选出一个数字
  
  
   
   x
  
  ,JSL看到这个数字之后从
  
  
   
   [l2,r2]
  
  中取出一个数字
  
  
   
   y
  
  
  
  
   
   y
  
  可能和
  
  
   
   x
  
  相同)。最后他们计算出数字
  
  
   
   z=xy
  
  
  
  
   
   
  
  为异或运算)。Alice希望
  
  
   
   z
  
  尽可能大,而JSL希望
  
  
   
   z
  
  尽可能小。Alice和JSL都很聪明,那么
  
  
   
   z
  
  最后会是多少?
输入描述
第一行一个数
  
  
   
   T
  
  ,表示数据组数。
对于每组数据有四个数
  
  
   
   l1,r1,l2,r2
  
  
  
  
   
   1T10000,0l1r1109,0l2r2109
  
  
输出描述
每组数据输出一行Case #
  
  
   
   x
  
  : 
  
  
   
   ans
  
  
  
  
   
   x
  
  表示组数编号,从
  
  
   
   1
  
  开始。
  
  
   
   ans
  
  
  
  
   
   z
  
  的值。
输入样例
2
1 4 3 8
1 3 4 7
输出样例
Case #1: 2
Case #2: 4
题解:

1.把数想成二进制形式,从最高位开始依次枚举,对于每一位,Alice的策略是尽量让数字(0,1)和Jsl不一样,而jsl

的策略是尽量使数字和Alice一样

2.dfs + 剪枝

3.比较重要的两个剪枝就是当Jsl可用数的范围大于了Alice,那么直接返回,不需要再搜索了

4.每次递归,都尽可能的缩小上界r。

总结:

1.这个题目没有自己做出来,第二个剪枝没有想出来,而且数位dp法也是不会,以后再补上这个题吧

2.记得当时第一次用贪心写的,思路是错的,以后如果一个题是躺在床上或吃着饭想出来的话就先在草稿纸上演算一

遍再敲代码比较稳妥

3.草稿纸也一定要干净利索!

4.把大任务分成小任务,说白了就是制定很多的小目标,加快想题速度!

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
int _,ans;
int state(int i,int l,int r)
{
    if((1 << i) <= l)return 1;
    else if((1 << i) > r)return 0;
    else return -1;
}
void deal(int & l,int & r,int v,int i)
{
    l = max(l - v,0);
    r = min(max(r - v,0),(1 << i) - 1);
}
void dfs(int l1,int r1,int l2,int r2,int i,int cur)
{
    if(l2 <= l1 && r1 <= r2 || i == -1)return;
    if(cur + ((LL)1 << (i + 1)) - 1 < ans)return;
    int st1 = state(i,l1,r1),st2 = state(i,l2,r2);
    if(st1 >= 0 && st2 >= 0)
    {
        cur |= ((st1 ^ st2) << i);
        ans = max(cur,ans);
        deal(l1,r1,st1 << i,i) , deal(l2,r2,st2 << i,i);
        dfs(l1,r1,l2,r2,i - 1,cur);
    }
    else if(st1 == -1 && st2 == -1)
    {
        dfs(l1,min(r1,(1 << i) - 1),l2,min(r2,(1 << i) - 1),i - 1,cur);
        deal(l1,r1,1 << i,i) , deal(l2,r2,1 << i,i);
        dfs(l1,r1,l2,r2,i - 1,cur);
    }
    else if(st1 >= 0 && st2 == -1)
    {
        deal(l1,r1,st1 << i,i) , deal(l2,r2,st1 << i,i);
        dfs(l1,r1,l2,r2,i - 1,cur);
    }
    else// if(st1 == -1 && st2 >= 0)
    {
        cur |= (1 << i);
        ans = max(cur,ans);
        deal(l1,r1,!st2 << i,i) , deal(l2,r2,st2 << i,i);
        dfs(l1,r1,l2,r2,i - 1,cur);
    }
}
int main()
{
    scanf("%d",&_);
    for(int kcas = 1;kcas <= _;kcas++)
    {
        int l1,l2,r1,r2;
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        ans = 0;
        dfs(l1,r1,l2,r2,30,0);
        printf("Case #%d: %d\n",kcas,ans);
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值