bestcoder #89 (hdu 5495) Fxx and game(单调队列优化dp)

很水的dp题,考虑 dp[i] 表示 x i 的最小花费,

dp[i]=min{dp[j]+1,dp[i/k]+1},k|i,it<=j<i,it

由于 t 可能会很大,所以可以用单调队列维护一下对于每个 i 的前 t 个数,的最小值。由于本人初次接触单调队列,所以写的有点复杂。。。

AC代码

#include 
#include
#include
#include
#define maxn 1000010
#define inf 0x3f3f3f3f
using namespace std;

template <typename Item>struct monotone_queue
{
    std::deque data,aux;//原本队列之外的辅助队列
    int size(){return data.size();}
    void push(Item it)
    {
        data.push_back(it);
        while(!aux.empty() && aux.back()>it)aux.pop_back();
        aux.push_back(it);
    }
    void pop()
    {
        if(data.front() == aux.front())aux.pop_front();
        data.pop_front();
    }
    Item top()
    {
        return aux.front();
    }
    void init(){
        data.clear();
        aux.clear();
    }
};

int dp[maxn];

int main()
{
    monotone_queue<int> mq;
    int x,k,t;
    int T;scanf("%d",&T);
    while(T--)
    {
        mq.init();
        scanf("%d%d%d",&x,&k,&t);
        memset(dp,0,sizeof(dp[0]));
        dp[1] =0;
        mq.push(dp[1]);
        for(int i=2 ;i<=x ; ++i)
        {
            dp[i] = inf;
            dp[i] = min(dp[i],mq.top()+1);
            if(i%k == 0){dp[i] = min(dp[i],dp[i/k]+1);}
            mq.push(dp[i]);
            if(mq.size()>t)mq.pop();
        }
        printf("%d\n",dp[x]);
    }
    return 0;
}

你可能感兴趣的:(算法刷题)