Educational Codeforces Round 16 E. Generate a String (DP)

Generate a String

題目連接:

http://codeforces.com/contest/710/problem/Eios

Description


zscoder wants to generate an input file for some programming competition problem.
His input is a string consisting of n letters 'a'. He is too lazy to write a generator so he will manually generate the input in a text editor.
Initially, the text editor is empty. It takes him x seconds to insert or delete a letter 'a' from the text file and y seconds to copy the contents of the entire text file, and duplicate it.
zscoder wants to find the minimum amount of time needed for him to create the input file of exactly n letters 'a'. Help him to determine the amount of time needed to generate the input.
spa

Input


The only line contains three integers n, x and y (1 ≤ n ≤ 107, 1 ≤ x, y ≤ 109) — the number of letters 'a' in the input file and the parameters from the problem statement.
code

Output


Print the only integer t — the minimum amount of time needed to generate the input file.
three

Sample Input

8 1 1
8 1 10

Sample Output

4
8


題意:


數num初始時爲0,能夠用x的花費加一或減一,能夠用y的花費乘二,求最小花費變成N.
ip


題解:


規模這麼大,要麼是找規律,要麼是O(n). 最短路什麼的確定不行了.
這裏用我爲人人的dp來解決:dp[i]: 達到i的最小花費.
枚舉i:對於i有三種拓展方向(加一 減一 乘二).
若是直接進行這三種拓展,確定存在問題:由於存在減一的操做,因此i的最小值可能會由i+1得來.
考慮一個點i,若是它的最小花費是由比i大的點拓展而來的,那麼這個點必定是i+1,且它是一個偶數.
證實:首先,由於比i大隻能減一操做,因此最小的必定是i+1.
其次,i+1這個數的來源有三種i,i+2,i/2. 確定不能是i(否者就重複走了),若是是i+2,那麼違背上一個條件(i+2連續減兩次到達i),因此必定是i/2經過乘二操做獲得i.
綜上,咱們只要在每次更新2n時,同時更新2n-1,便可保證每次枚舉到i時,dp[i]都是最小.
這題也能夠寫成"人人爲我"的形式,見代碼註釋.
get


代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <list>
#define LL long long
#define eps 1e-8
#define maxn 10000100
#define mod 100000007
#define inf 0x3f3f3f3f3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;

LL dp[maxn];

int main(int argc, char const *argv[])
{
    //IN;

    int n; LL x,y;
    while(scanf("%d %I64d %I64d", &n,&x,&y) != EOF)
    {
        memset(dp, inf, sizeof(dp));
        dp[1] = x;
        for(int i=1; i<=n; i++) {
            dp[i+1] = min(dp[i+1], dp[i] + x);
            if(i*2 < maxn) {
                dp[i*2] = min(dp[i*2], dp[i] + y);
                dp[i*2-1] = min(dp[i*2-1], dp[i*2] + x);
            }
        }

        /*
            "我爲人人"
            for(int i=1; i<=n; i++) {
                dp[i] = min(dp[i-1]+x, dp[(i+1)/2]+y+(i%2)*x);
            }
        */

        printf("%I64d\n", dp[n]);
    }

    return 0;
}
相關文章
相關標籤/搜索