SPOJ系列 —— SPOJ346

SPOJ 346

#dynamic program

In Byteland they have a very strange monetary system.

Each Bytelandian gold coin has an integer number written on it. A coin (n) can be exchanged in a bank into three coins:$ n/2$, (n/3) and (n/4). But these numbers are all rounded down (the banks have to make a profit).

You can also sell Bytelandian coins for American dollars. The exchange rate is (1:1). But you can not buy Bytelandian coins.

You have one gold coin. What is the maximum amount of American dollars you can get for it?

(0 <= n <= 1 000 000 000)

这题实际上就是一个递推式:

[dp(n) = max(n, dp(lfloorfrac{n}{2} floor) + dp(lfloorfrac{n}{3} floor) + lfloorfrac{n}{4} floor) ]

但是由于n很大,简单的递推会出现很多重复运算,又因为n很大无法直接开这么大的数组,因此我们可以先预处理计算出n <= 1e5的数据,并记忆化搜索这些数据即可。因此本题还算非常basic(of course, u can use map or unordered_map to maintain the value.)

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

using ll = long long;


const int maxn = 1e6 + 50;
ll dp[maxn];

ll helper(int cur){
    if (cur < maxn && dp[cur] != -1) return dp[cur];
    if (cur < 12) return dp[cur] = cur;

    ll ans = helper(cur / 2) + helper(cur / 3) + helper(cur / 4);
    if (cur < maxn) dp[cur] = ans;
    return ans;
}

int main(){
    memset(dp, -1, sizeof(dp));
    int n;

    while (std::cin >> n)
        std::cout << helper(n) << "
";
    
    return 0;
}

/* SPOJ 346 Memo dp */

if u want use python to solve this problem, and u should deal with the I/O problem.

You can use the follow code to finish the function like while (std::cin >> n) in C/C++

def rdi(): return int(input())
dp = {}

def f(x):
    if (x < 12): return x
    if (x in dp): return dp[x]
    ans = f(x // 2) + f(x // 3) + f(x // 4)
    dp[x] = ans
    return ans


while True:
    try:
        n = rdi()
        print(f(n))

    except EOFError:
        break

原文地址:https://www.cnblogs.com/Last--Whisper/p/14818598.html