(DP)codeforces

原题链接:http://www.codeforces.com/problemset/problem/710/E


题意:一个字符串,开始长度为0,目标长度为n,长度+1或-1需要的时间为x,长度*2需要的时间为y,求0到m需要的最少时间。


分析:这题一上来直接写优先队列bfs,然后很愉快的超内存的了。就想别的方法,想了一会没想清晰,感觉可以用记忆化搜索,就往这上面一想,才发现直接dp就行了。

可以很容易发现,奇数肯定是+1或者通过*2逼近并且+1或-1得到。

而偶数只能在+1和翻倍得到。

所以在奇数情况下的状态转移方程为dp[i]=min(dp[i-1]+x,dp[i/2]+x+y,dp[i/2+1]+x+y)

偶数情况下的为dp[i]=min(dp[i-1]+x,dp[i/2]+y)


代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<vector>
#include<queue>
#include<map>
#include<list>
#include<bitset>
#include<string>
#include<cctype>
#include<cstdlib>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int inf = 1 << 30;
const ll lnf = 1ll << 60;

//-----upstair is template------//

const int maxn=1e7;
ll dp[maxn];

void solve() {
    int n,x,y;
    scanf("%d%d%d",&n,&x,&y);
    fill(dp,dp+maxn,lnf);
    dp[0]=0;
    for(int i=1;i<=n;i++){
        if(i&1){
            dp[i]=min(dp[i-1]+x,min(dp[i/2+1]+x+y,dp[i/2]+x+y));
        }
        else{
            dp[i]=min(dp[i-1]+x,dp[i/2]+y);
        }
    }
    printf("%I64d
",dp[n]);
}


int main() {

#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif
    //iostream::sync_with_stdio(false);
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/tak-fate/p/5811471.html