lift and throw

本文探讨了一个涉及游戏角色移动策略的问题,通过深度优先搜索算法来寻找角色所能达到的最大位置。考虑到角色间的相互作用及其移动限制,文章提供了一种实现方案并详细解释了其运行逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述
  给定一条标有整点(1, 2, 3, …)的射线. 定义两个点之间的距离为其下标之差的绝对值.
  Laharl, Etna, Flonne一开始在这条射线上不同的三个点, 他们希望其中某个人能够到达下标最大的点.
  每个角色只能进行下面的3种操作, 且每种操作不能每人不能进行超过一次.
  1.移动一定的距离
  2.把另一个角色高举过头
  3.将举在头上的角色扔出一段距离
  每个角色有一个movement range参数, 他们只能移动到没有人的位置, 并且起点和终点的距离不超过movement range.
  如果角色A和另一个角色B距离为1, 并且角色B没有被别的角色举起, 那么A就能举起B. 同时, B会移动到A的位置,B原来所占的位置变为没有人的位置. 被举起的角色不能进行任何操作, 举起别人的角色不能移动.同时, 每个角色还有一个throwing range参数, 即他能把举起的角色扔出的最远的距离. 注意, 一个角色只能被扔到没有别的角色占据的位置. 我们认为一个角色举起另一个同样举起一个角色的角色是允许的. 这种情况下会出现3个人在同一个位置的情况. 根据前面的描述, 这种情况下上面的两个角色不能进行任何操作, 而最下面的角色可以同时扔出上面的两个角色. 你的任务是计算这些角色能够到达的位置的最大下标, 即最大的数字x, 使得存在一个角色能够到达x.
输入格式
  输入共三行, 分别为Laharl, Etna, Floone的信息.
  每一行有且仅有3个整数, 描述对应角色的初始位置, movement range, throwing range.
  数据保证3个角色的初始位置两两不相同且所有的数字都在1到10之间.
输出格式
  仅有1个整数, 即Laharl, Etna, Flonne之一能到达的最大距离.
样例输入
9 3 3
4 3 1
2 3 3
样例输出
15
样例说明
  一开始Laharl在位置9, Etna在位置4, Flonne在位置2.
  首先, Laharl移动到6.
  然后Flonne移动到位置5并且举起Etna.
  Laharl举起Flonne将其扔到位置9.
  Flonne把Etna扔到位置12.
  Etna移动到位置15.

思路:题目提示说深度优先搜索,根据问题描述也就是三个人分别三种操作而且每种操作每个人最多执行一次那就是说满打满算九个操作,一开始就想到了全排列

      当然每个操作都是有条件的,比如移动不能移动到有人的位置,只能举起距离为一并且没有被举起来的人等等。深搜的时候注意各个人状态标志在允许的条件下进行操作

结果提交:超时 90 分。。。 搜索超时需要剪枝!比如第一步不能进行抛操作等等

Talk is cheap Show me the code !

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

using namespace std;

int ans;
int pos[3];
int mr[3];
int tr[3];
int orders[9];//三个人三个操作 共计九个操作 

//判断x是否被占用 
bool isOccupied(int x,int curPerson,int *posCur)
{
    for(int i=0;i<3;i++)
    {
        if(i!=curPerson&&posCur[i]==x)
            return true;
    }
    return false;
}

bool isPersonBack(int x,int *posCur)
{
    for(int i=0;i<3;i++)
    {
        if(x>posCur[i])
            return true;
    }
    return false;
}

void pprint(int *posCur,int *lift,int *lifted)
{
    char s[10];
    //gets(s);
    printf("%d %d %d\n",posCur[0],posCur[1],posCur[2]);
    printf("%d %d %d\n",lift[0],lift[1],lift[2]);
    printf("%d %d %d\n",lifted[0],lifted[1],lifted[2]);
    for(int i=0;i<9;i++)
    {
        printf("%d%c",orders[i],i==8?'\n':' ');
    }
}

void findMax(int cur,int *posCur,int *lift,int *lifted)
{
    if(cur>9)
        return;
    for(int i=0;i<9;i++)
    {
        if(!orders[i])
        {
            //opration(i,posCur,lift,lifted);
            //根据操作数找到当前Person和opration完成操作 
            int curPerson = i / 3;
            int curPersonOp = i % 3;
            //移动一定距离  没有举人  也没被人举着 
            if(curPersonOp==0&&lifted[curPerson]==-1&&lift[curPerson]==-1)//移动只需恢复移动的人到原来的位置
            {
                if(cur==9)
                {
                    ans = max(ans,posCur[curPerson]+mr[curPerson]);
                    return;
                }
                int nowPos = posCur[curPerson];//将当前位置保留下来  以便恢复状态  继续深搜 
                for(int j=1;j<=mr[curPerson];j++)
                {
                    int forward = j + nowPos;//前进 
                    int back = nowPos - j;//后退
                    if(!isOccupied(forward,curPerson,posCur))
                    {
                        orders[i] = 1;
                        ans = max(ans,forward);
                        posCur[curPerson] = forward;
                        //pprint(posCur,lift,lifted);
                        findMax(cur+1,posCur,lift,lifted);
                        posCur[curPerson] = nowPos;//恢复状态
                        orders[i] = 0;
                    }
                    if(back>0&&!isOccupied(back,curPerson,posCur)&&isPersonBack(back,posCur))
                    {
                        orders[i] = 1;
                        posCur[curPerson] = back;
                        findMax(cur+1,posCur,lift,lifted);
                        posCur[curPerson] = nowPos;//恢复状态
                        orders[i] = 0;
                    }
                }

            }
            //举人  必须  自己没有被举起来  而且现在没有举着别人 
            else if(curPersonOp==1&&lifted[curPerson]==-1&&lift[curPerson]==-1)//举起别人需要恢复 被举前 被举人的状态  和举起人的状态 
            {
                for(int j=0;j<3;j++)
                {
                    if(abs(posCur[j]-posCur[curPerson])==1&&lifted[j]==-1) //距离为1,并且没有被举起来 
                    {
                        int midPos = posCur[j];
                        posCur[j] = posCur[curPerson];
                        lifted[j] = curPerson;
                        lift[curPerson] = j;
                        if(lift[j]!=-1)
                        {
                            posCur[lift[j]] = posCur[j];
                        }
                        orders[i] = 1;
                        findMax(cur+1,posCur,lift,lifted);
                        //下面开始恢复
                        orders[i] = 0;
                        lift[curPerson] = -1;
                        lifted[j] = -1;
                        posCur[j] = midPos;
                        if(lift[j]!=-1)
                        {
                            posCur[lift[j]] = posCur[j];
                        }
                    }
                }
            }
            //扔人 必须举着人呢 而且 自己没有被举起来 
            else if(cur>1&&curPersonOp==2&&lift[curPerson]!=-1&&lifted[curPerson]==-1)//需要恢复举和被举的状态 
            {
                if(cur==9)
                {
                    ans = max(ans,posCur[curPerson]+tr[curPerson]);
                    return;
                }
                for(int j=1;j<=tr[curPerson];j++)
                {
                    if(!isOccupied(posCur[curPerson]+j,lift[curPerson],posCur))
                    {
                        orders[i] = 1;
                        int mid = lift[curPerson];//举着谁 
                        posCur[mid] = posCur[curPerson] + j;
                        ans = max(ans,posCur[mid]);
                        //pprint(posCur,lift,lifted);
                        lift[curPerson] = -1;
                        lifted[mid] = -1;
                        if(lift[mid]!=-1)//如果最上面还有人 
                        {
                            int top = lift[mid];
                            posCur[top] = posCur[mid];
                        }
                        findMax(cur+1,posCur,lift,lifted);
                        //下面是状态恢复
                        orders[i] = 0;
                        lift[curPerson] = mid;
                        lifted[mid] = curPerson;
                        posCur[mid] = posCur[curPerson];
                        if(lift[mid]!=-1)
                        {
                            int top = lift[mid];
                            posCur[top] = posCur[mid];
                        }
                    }
                }
            }
        }
    }
}

int main(int argc, char *argv[]) {
    for(int i=0;i<3;i++)
    {
        scanf("%d%d%d",pos+i,mr+i,tr+i);
    }
    int posCur[3];
    int lift[3]; memset(lift,-1,sizeof(lift));//举起谁  -1谁也没举 
    int lifted[3];  memset(lifted,-1,sizeof(lifted));//被谁举起  -1谁也没被举
    posCur[0] = pos[0];
    posCur[1] = pos[1];
    posCur[2] = pos[2];
    for(int i=0;i<3;i++) ans = max(ans,pos[i]);
    memset(orders,0,sizeof(orders));//初始化操作 
    int start = 1;
    findMax(start,posCur,lift,lifted);
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值