【OJ】抓牛问题

追牛算法挑战
本文介绍了一个有趣的算法问题:农夫如何在数轴上用最少时间追上逃跑的奶牛。通过使用广度优先搜索(BFS)算法,文章详细解释了如何解决这一问题,包括代码实现和样例输入输出。
/*
农夫John的奶牛跑路了。将地图视作一条数轴,John的初始位置在s而奶牛的位置在t(0<=s,t<=100000)。John可以花费一分钟的时间使自己作如下移动:

1 从点x移动到点x+1
2 从点x移动到点x-1
3 从点x移动到点x*2
奶牛的位置一直在点t。现在给定s,t,要求John要追上奶牛最少需要几分钟。

Sample Input:
5 17

Sample Output:
4

Description:
5->4->8->16->17
*/

#include<iostream>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;
const int M=100010;

int bfs(int s,int t)
{
    queue<int> q;
    int head,next;
    int vis[M],step[M];
    memset(vis,0,sizeof(vis));
    memset(step,0,sizeof(step));
    q.push(s);
    step[s]=0;
    
    while(!q.empty())
    {
        head=q.front();
        q.pop();
        for(int i=0;i<3;i++)
        {
            if(i==0)
                next=head-1;
            if(i==1)
                next=head+1;
            if(i==2)
                next=head*2;
            if(next<0||next>M)
                continue;
            if(vis[next]==0)
            {
                vis[next]++;
                step[next]=step[head]+1;
                q.push(next);
            }
            if(next==t)
                return step[next];
        }
    }
}


int main()
{
    int s,t;
    while(scanf("%d %d",&s,&t)==2&&s>=0&&t<=M)
    {
        if(t<=s)//牛在人后面 
            cout<<abs(s-t)<<endl;
        else 
            cout<<bfs(s,t)<<endl;
    }
    
    return 0;
}


/*
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
 
const int maxn=100001;
 
bool vis[maxn];//标记数组
int step[maxn];//记录到了每一位置所走的步数
queue <int> q;//定义队列
 
int bfs(int n,int k)
{
    int head,next;
    q.push(n);   //开始FJ在n位置,n入队
    step[n]=0;
    vis[n]=true; //标记已访问
    while(!q.empty())  //当队列非空
    {
        head=q.front();  //取队首
        q.pop();         //弹出对首
        for(int i=0;i<3;i++)     //FJ的三种走法
        {
            if(i==0) next=head-1;
            else if(i==1) next=head+1;
            else next=head*2;
            if(next<0 || next>=maxn) continue; //排除出界情况
            if(!vis[next])  //如果next位置未被访问
            {
                q.push(next);    //入队
                step[next]=step[head]+1;  //步数+1
                vis[next]=true;  //标记已访问
            }
            if(next==k) return step[next];  //当遍历到结果,返回步数
        }
    }
}
int main()
{
    int n,k;
    while(cin>>n>>k)
    {
        memset(step,0,sizeof(step));
        memset(vis,false,sizeof(vis));
        
        while(!q.empty()) q.pop(); //注意调用前要先清空
        if(n>=k) printf("%d\n",n-k);
        else printf("%d\n",bfs(n,k));
    }
    return 0;
}
*/

/*
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include <algorithm>
using namespace std;
 
queue<int> q;
int  m,n;
int step[100010];
int vis[100010];
int rear,front;//rear表示下一步 
int BFS(){
    int i;
    q.push(n);//把农民的位置压入队列 
    step[n]=0;//步数记为0 
    vis[n]=1;////标记这个点走过 
    while(!q.empty()){//队列不为空哦时执行 
        front=q.front();//最开始的位置 
        q.pop();//弹出队列头 
        for(i=0;i<3;i++)//三种走法,三种循环 
        {
            if(i==0)
            rear=front+1;//第一种下一步+1 
            if(i==1)
            rear=front-1;//第二种下一步-1 
            if(i==2)
            rear=front*2;//第三种步数翻倍 
            if(rear>=0&&rear<=100000&&vis[rear]==0)//判断是否越界,并且这一步没有走过 
            {
                vis[rear]=1;//标记这一步走过了 
                step[rear]=step[front]+1;// 步数+1 
                q.push(rear);//将当前位置压入队列 
            }
            if(rear==m)return step[rear];
        }
    }return -1;
    
}
 
int main()
{
    
    cin>>n>>m;
        memset(step,0,sizeof(step));//初始化为0 
        memset(vis,0,sizeof(vis));//初始化为false
        cout<<BFS();
    
    return 0;
}
*/

 

 

tz@HZAU

2019/3/4

转载于:https://www.cnblogs.com/acm-icpcer/p/10469323.html

<think>嗯,用户问的是OJ平台上的“奶塔”问题的解决方案或题解。首先,我需要确定这个具体的问题内容,因为不同的OJ可能有不同的题目名称相同的情况。但根据用户提供的引用信息,尤其是引用[4]中的描述,提到输入的minSPFmaxSPF值,这可能与防晒霜分配问题有关,或者类似的问题结构。比如,可能类似于USACO中的“防晒”题目,其中需要为每头分配防晒霜,使其SPF值在的minmax范围内。 接下来,用户提到的“奶塔”可能是指需要按照某种条件堆叠奶,形成一个塔结构,可能涉及动态规划或贪心算法。例如,每头有重量力量,要求堆叠时每层的重量总不超过下层的力量。这时候,问题可能类似于经典的“奶塔”问题,其中需要最大化塔的高度,同时满足每层的承重限制。 根据引用[4]中的输入格式,每头有minmax的SPF,可能题目中的条件与这些值有关。例如,可能每头需要放置在塔中,且必须满足某种SPF的条件,如每层的SPF总或某种累积值不超过某个限制。或者,可能问题中的“塔”需要满足每头的属性(如高度、重量等)的某种排列组合。 接下来,我需要结合常见的OJ题目来推断可能的解法。例如,如果问题类似于“防晒”问题,那么贪心算法可能适用,即按的maxSPF排序,然后为每头分配可用的最小SPF值。或者,如果是堆叠问题,可能需要按某种顺序排列奶,比如按力量加上重量排序,以最大化塔的高度。 根据用户提供的引用[3]中的输入参数A、B、L,可能问题涉及支持人数、反对人数上限,这可能与投票机制有关,但用户的问题是关于奶塔,所以可能需要更多的信息。但结合引用[4]中的输入格式,每头有minSPFmaxSPF,可能的题目是要求选择最多的,使得它们的SPF值满足某种条件,比如总不超过L,或者每个的SPF在某个范围内。 假设问题的大意是:给定每头的minmax SPF,以及一个总上限L,选择若干头,使得它们的SPF总不超过L,并且每头的SPF在其minmax之间。目标是最多选择的数量,即最大化数量。这种情况下,可能需要使用贪心算法,按某种顺序选择,尽可能选SPF小的,以腾出更多空间给其他。 例如,可能的解法是按的max SPF从小到大排序,然后依次选择每头,并取该的min SPF(或者尽可能小的SPF值),这样总最小,可以选更多的。或者,如果问题允许SPF为某个固定值,但需要满足每头的min <= SPF <= max,并且总不超过L,那么可能需要动态规划或其他方法。 不过,用户的问题是关于“奶塔”的,可能更偏向于堆叠问题,而非防晒问题。例如,每头有高度重量,塔的高度是各高度之,而每层的重量之不能超过下层的力量。这种情况下,动态规划可能被用来计算最大高度,或者贪心算法确定最优排列顺序。 比如,经典问题中,最优排列是按的(力量 + 重量)进行排序,这样可以得到最大的可能高度。因此,可能的解法是按照的(力量 + 重量)升序排列,然后使用动态规划来计算每层可能的累积重量最大高度。 总结可能的步骤: 1. 确定题目具体要求:比如,堆叠的条件是什么?可能每头有重量力量,堆叠时上面的总重量不超过下面的力量。目标是塔的最大高度。 2. 输入可能是每头的重量力量,或者minmax SPF之类的参数,需要根据引用中的输入格式推测。 3. 解法可能涉及排序(如按力量+重量)动态规划,或者贪心选择。 由于用户提到的引用[4]中的输入是minSPFmaxSPF,可能题目中的需要被分配一个SPF值,使得它们的总不超过L,并且每个的SPF在[min, max]范围内。这可能类似于背包问题,但需要选择每个物品的某个值在区间内,总不超过容量,同时最大化数量或总价值。例如,最大化的数量,使得它们的SPF总<=L,每个的SPF在[min_i, max_i]之间。 这种情况下,可能需要贪心算法,优先选择maxSPF较小的,并为它们分配尽可能小的SPF值,这样总更小,可以选更多。例如,按maxSPF升序排序,然后依次为每头取minSPF,如果总不超过L,就选这头,否则跳过。或者,如果允许在[min, max]之间调整,可以尽可能取最小的可能SPF,以留出更多L给其他。 因此,解决方案的步骤可能如下: 1. 将按maxSPF升序排序,这样优先处理maxSPF小的,因为它们的选择更灵活。 2. 对于每头,选择其minSPF到maxSPF之间的最小值,使得总尽可能小,从而可以选更多。 3. 累加这些最小值,到总超过L为止,此时记录已选的数。 或者,可能题目允许在总不超过L的情况下,每个的SPF可以取任意值在[min, max]之间,求最多可以选多少头。这时,最优策略是尽可能选择那些maxSPF小的,并且为它们分配最小的可能SPF(即minSPF),这样总最小,可以选最多。 例如,步骤如下: - 按的maxSPF升序排序。 - 初始化总sum=0,计数count=0。 - 遍历排序后的,对于每头,若sum + minSPF <= L,则选这头,sum += minSPF,count +=1;否则,跳过。 这样,这样可以得到最多的数,因为每次选的是当前可选中maxSPF最小的,且分配最小的SPF,从而为后面的留出更多空间。 如果题目要求总不超过L,同时每个的SPF必须在其范围内,那么这种贪心策略是正确的。因为如果存在另一种选择方式,选不同的,可能总更小,但此时maxSPF更大的可能占据了更多的机会,而按maxSPF升序可以保证先处理限制更严格的,从而最大化数量。 例如,假设有两头A(min=2, max=3),B(min=1, max=4)。L=4。如果先选B,分配1,总1,然后选A,分配2,总3,总选2头。如果先选A,分配2,总2,然后选B分配1,总3,同样选2头。但若L=3,则两种顺序都选2头。但如果L=3,而B的min是2,那么可能不同。所以排序的关键是优先处理maxSPF小的,这样它们的maxSPF较小,意味着如果现在不选它们,之后可能无法选(因为后面的maxSPF更大,可能需要更大的SPF值)。 综上,解决方案可能是这样的排序加贪心选择。因此,在回答中需要说明这一点,并给出具体的步骤可能的代码实现。</think>### OJ问题解决方案分析 根据题目描述引用信息[^4],推测问题核心为:给定每头的SPF范围$[minSPF_i, maxSPF_i]$总上限$L$,选择若干头并为其分配SPF值,使得总SPF不超过$L$且每个SPF值在对应范围内,目标最大化选数量。 #### 解决思路 1. **贪心策略选择** 将按$maxSPF$升序排序,优先处理限制更严格的。为每头分配最小的可行SPF值(即$minSPF$),确保总消耗最小。 2. **数学证明** 假设存在最优解中某头未被选中,但按此策略应被选中。由于$maxSPF$更小的具有更严格的约束,优先选择它们不会影响后续更宽松的的选择空间[^1]。 #### 实现代码示例 ```python n = int(input()) # 输入的数量 cows = [] for _ in range(n): min_spf, max_spf = map(int, input().split()) cows.append((max_spf, min_spf)) cows.sort() # 按maxSPF升序排列 total = 0 count = 0 L = int(input()) # 总SPF上限 for max_spf, min_spf in cows: if total + min_spf <= L: total += min_spf count += 1 else: break print(count) ``` #### 关键步骤说明 1. **排序逻辑**:按$maxSPF$升序确保优先处理限制严格的。 2. **分配策略**:为每头分配$minSPF$,使总SPF最小化,从而容纳更多[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值