网易笔试的两道dp问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pp634077956/article/details/68068371

已知一个数字中某些位数被模糊,同时这个数能够被k整除,那么这个数有多少种可能?简单的方法就是用dp来统计所有的状态,注意状态的表示是用余数来表示的。状态转移的时候统计一下数量就好。

#include "iostream"
#include "vector"
#include "algorithm"
#include "string"
#include "cmath"
using namespace std;



int main(void){

    int n;
    string k;
    while (cin >> k)
    {
        cin >> n;
        int num = k.size();
        int count = 0;
        long long sum = 0;
        int usum = 0;
        long long unknown[20] = { 0 };
        for (int i = 0; i < num; ++i)
        {
            if (k[i] == 'X')
            {
                count += 1;
                unknown[num - i - 1] = pow(10, num - i - 1);
                sum *= 10;
            }
            else
                sum = sum * 10 + k[i] - '0';

        }
        vector<long long> dp(n, 0);
        dp[0] = 1;
        int c = (n - sum%n) % n;
        for (int i = 0; i < num; ++i)
        {
            if (unknown[i] == 0)
                continue;

            vector<long long> tmpdp(n, 0);

            for (int s = n - 1; s >= 0; --s)
            {
                if (dp[s])
                {
                    for (int j = 0; j < 10; ++j)
                        tmpdp[(s + unknown[i] * j) % n] += dp[s];
                }
            }
            dp = tmpdp;
        }
        cout << dp[c] << endl;
    }
    return 0;
}

有n个砖头,用这些砖头构建两个相同高度的最高的塔?不一定全部用完这些砖头。这道题可暴力加剪枝(其实我很奇怪暴力居然可以过),或者dp解决,告诉你输出不超过50w,所以状态可以写成dp[d],d代表两个塔的高度只差,dp[d]代表其中的最大高度。这样写的好处就在于用状态自己的值也作为状态的一部分,否则状态表示成dp[left][right]那么数量就爆炸了。

#include "iostream"
#include "vector"
#include"algorithm"
#include "cmath"
using namespace std;

int main() {
    int n = 0;
    while (cin >> n){
        vector<int> a(n);
        int sum = 0;
        for (int i = 0; i < n; ++i) {
            cin >> a[i];
            sum += a[i];
        }
        sum = min(sum, 500000);
        vector<int> dp(sum + 1, -1);
        dp[0] = 0;
        dp[a[0]] = a[0];

        for (int i = 1; i < n; ++i) {
            vector<int> tmp(dp);
            int h = a[i];
            for (int j = 0; j <= sum; ++j) {
                if (j + h <= sum && dp[j + h] != -1)// push A
                    tmp[j] = max(tmp[j], dp[j+h]);


                if (j - h >= 0 && dp[j - h] != -1)// push B
                    tmp[j] = max(tmp[j], dp[j - h] + h);
                else if (j - h < 0 && dp[h - j] != -1)
                    tmp[j] = max(tmp[j], dp[h-j]+j);



            }
            dp = tmp;
        }

        cout << (dp[0]==0 ? -1:dp[0] )<< endl;

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pp634077956/article/details/68068371