HDU 5945 Fxx and game 单调队列||bfs

传送门:HDU5945

题意:给定3个数x,k,t,和两种操作

1)  x=x-i;0<=i<=t;

2)  if x|k  x=x/k;

问最少经过多少步能将x变为1,输入保证x能变为1.

比赛的时候看这题的想法是广搜,但是第一次交MLE,一顿xjb改以后又交了一次,竟然过了,就没再多想,结果终测还是MLE。。后来看题解大多数都是用dp+单调队列做的,但是bfs也不是不可以,不过要加一个标记数组。把比赛时的代码拿来加上标记数组改了改,怎么交怎么RE,又去看题解发现题解是从x往1搜,而我是从1往x搜,又改一发才终于AC。

下面是BFS代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include<math.h>
#define inf 0x3f3f3f3f
#define M 1000005
using namespace std;
int x,k,t;
int book[M]; 
int ans=inf;
struct node{
    int num,t;
};
int bfs()
{
    if(k==1&&t)
    return (x-1+t-1)/t;
    memset(book,0,sizeof(book));
    queue<node>q;
    node a;
    a.num=x;
    a.t=0;
    q.push(a);
    book[x]=1;
    while(!q.empty())
    {
        node b=q.front();
        q.pop();
        node c;
        if(b.num==1)
        return b.t;
        if(2<=b.num&&b.num<=(t+1)||b.num==k)//这里有个BUG不知道为啥,就是把b.num==k注释掉以后再交是WA
        return b.t+1;//但是我觉得顶多会多运行几次啊,这条语句应该是剪枝啊。。不明白把剪枝去掉以后怎么就WA了。。
        if(b.n
        {
            c.num=b.num/k;
            c.t=b.t+1;
            q.push(c);
            book[b.num/k]=1;
        }
        //int m=min(t,b.num-1);
        for(int i=t;i>=1;i--)
        {
            if(!book[b.num-i])
            {
                c.num=b.num-i;
                c.t=b.t+1;
                q.push(c);
                book[b.num-i]=1;
            }
            else
            break;
        }        
    }
}
int main()
{
    int a;
    scanf("%d",&a);
    while(a--)
    {
        scanf("%d%d%d",&x,&k,&t);        
        printf("%d\n",bfs());
    }
return 0;
}

下面来说单调队列,这个就有点强了,以前只是接触过单调栈,这次又涨了新知识。

不瞎扯,下面是我觉得挺好理解的单调队列的学习博客:

点击打开链接    点击打开链接

下面是我觉得解释的比较明白的两篇题解。。

点击打开链接     点击打开链接

再下面就是我自己的代码了。。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct node{
	int num,id;
}q[1000005];
int dp[1000005];
int main()
{
	int x,k,t;
	int cnt;
	scanf("%d",&cnt);
	while(cnt--)
	{
		memset(dp,127,sizeof(dp));
		//memset(q,0,sizeof(q));
		scanf("%d%d%d",&x,&k,&t);
		int head=1,tail=1;
		dp[1]=0;
		q[tail].num=dp[1];
		q[tail].id=1;
		for(int i=2;i<=x;i++)
		{
			while(tail>head&&q[head].id<max(1,i-t))
			head++;			
			dp[i]=min(dp[i],q[head].num+1);
			if(i%k==0)dp[i]=min(dp[i],dp[i/k]+1);
			while(tail>=head&&dp[i]<=q[tail].num)
			tail--;
			tail++;
			q[tail].num=dp[i];
			q[tail].id=i;
		}
		printf("%d\n",dp[x]);
	}
return 0;
}

有趣的是bfs比单调队列快好多。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值