【HDU 5945 Fxx and game】+ 单调队列

来源:互联网 发布:手机版玻璃优化软件 编辑:程序博客网 时间:2024/05/16 07:41

Fxx and game
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 677 Accepted Submission(s): 159

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=X−i(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(1≤T≤20) indicating the number of test cases.

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

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
BestCoder Round #89

Recommend
wange2014 | We have carefully selected several similar problems for you: 5947 5946 5943 5942 5941

Statistic | Submit | Discuss | Note

单调队列 ,附上两种实现代码~~~严格意义上来说,第一种更符合单调队列的原本定义,第二中更容易理解点~~~

数组 + AC代码 :

#include<bits/stdc++.h>using namespace std;const int KK = 1e6 + 5;int dp[KK],vis[KK];int main(){    int T,x,k,t;    scanf("%d",&T);    while(T--){        scanf("%d %d %d",&x,&k,&t);        fill(vis + 1 , vis + 1 + x,KK);        int l = 1,r = 1; dp[1] = 1; vis[1] = 0;        for(int i = 2 ; i <= x ; i++){            while(l <= r && dp[l] < i - t) l++; // 更新首位置            if(l <= r) vis[i] = min(vis[i],vis[dp[l]] + 1); // 如果单调队列不为空            if(i % k == 0) vis[i] = min(vis[i],vis[i / k] + 1);            while(l <= r && vis[dp[r]] >= vis[i]) r--; // 更新最优解            dp[++r] = i;        }        printf("%d\n",vis[x]);    }    return 0;}

队列 + AC代码 :

#include<bits/stdc++.h>using namespace std;const int KK = 1e6 + 5;queue <int> q;int dp[KK];int main(){    int T,x,k,t;    scanf("%d",&T);    while(T--){        scanf("%d %d %d",&x,&k,&t);        fill(dp + 1,dp + x + 1,KK);        while(!q.empty()) q.pop();        dp[1] = 0;q.push(1);        for(int i = 1 ; i <= x ; i++){            while(!q.empty() && q.front() < i - t) q.pop(); // i 可以由大于 i - t 范围内的数得到            if(!q.empty()) dp[i] = min(dp[i],dp[q.front()] + 1);            if(i % k == 0) dp[i] = min(dp[i],dp[i / k] + 1);            while(!q.empty() && dp[q.front()] >= dp[i]) q.pop(); // 更新最优解            q.push(i);        }        printf("%d\n",dp[x]);    }    return 0;}
0 0
原创粉丝点击