BestCoderRound#89 HDU 5945 Fxx and game【单调队列+DP】

153 篇文章 0 订阅
18 篇文章 0 订阅

Fxx and game

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 816    Accepted Submission(s): 201


Problem Description
Young theoretical computer scientist Fxx designed a game for his students.

In each game, you will get three integers  X,k,t .In each step, you can only do one of the following moves:

1.X=Xi(0<=i<=t) .

2. if  k|X,X=X/k .

Now Fxx wants you to tell him the minimum steps to make  X  become 1.
 

Input
In the first line, there is an integer  T(1T20)  indicating the number of test cases.

As for the following  T  lines, each line contains three integers  X,k,t(0t106,1X,k106)

For each text case,we assure that it's possible to make  X  become 1。
 

Output
For each test case, output the answer.
 

Sample Input
  
  
2 9 2 1 11 3 3
 

Sample Output
  
  
4 3
 

Source
 

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5945

中文链接:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=730&pid=1002

题意:

一开始你将会得到一个数\:XX,每次游戏将给定两个参数\:k,tk,t, 任意时刻你可以对你的数执行下面两个步骤之一:

1.\:X = X - i(1 <= i <= t)1.X=Xi(1<=i<=t)2.\:2.\:X\:X\:k\:k的倍数,X = X / kX=X/k。

现在Fxx想要你告诉他最少的运行步骤,使\:X\:X变成\:11

此题也有人用DFS,BFS解决的,但出题人的题解是单调队列+DP

\:F_i\:Fi表示将\:i\:i变为\:1\:1的最少步骤,如果\:k|i,F_i=min{F_j,F_{\frac{i}{k}}}ki,Fi=min{Fj,Fki},否则\:F_i=min{F_j}Fi=min{Fj},其中\:i-t\leq j\leq i-1itji1

用单调队列维护一下就好了。

时间复杂度\:O(n)O(n)

单调队列的介绍: http://blog.csdn.net/dgq8211/article/details/7430726

http://blog.csdn.net/yjf3151731373/article/details/52971482

参考博客:http://blog.csdn.net/acmore_xiong/article/details/52969485

#include <bits/stdc++.h>
using namespace std;

int T, X, k, t;

const int MAXN = 1e6 + 5;
const int INF = 0x3f3f3f3f;

queue<int> Q;
int dp[MAXN];

int main()
{
    scanf("%d", &T);
    while(T --)
    {
        scanf("%d %d %d", &X, &k, &t);
        memset(dp, 0x3f, sizeof(dp));
        while(!Q.empty()) Q.pop();
        dp[1] = 0;
        Q.push(1);
        for(int z = 1; z <= X; z++)
        {
            while(!Q.empty() && Q.front() < z - t)
                Q.pop();
            if(!Q.empty())
                dp[z] = min(dp[z], dp[Q.front()] + 1);
            if(z % k == 0)
                dp[z] = min(dp[z], dp[z / k] + 1);
            while(!Q.empty() && dp[Q.front()] >= dp[z])
                Q.pop();
            Q.push(z);
        }
        printf("%d\n", dp[X]);
    }
    return 0;
}

尊重原创,转载请注明出处:http://blog.csdn.net/hurmishine



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值