训练营第七天--实战DP

一、背包问题

背包问题描述:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,每件物品数量只有一个,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?

动态规划的基本思路:将该问题转换成子问题,考虑五件物品在给定承重 C 的背包下最大价值为原问题,如下表所示,即为考虑abcde,C = 10时的最大价值,假设为f[5][10],原问题的解可以分解为两种情况,第一种情况是不考虑放入a只考虑放入bcde承重为C时的最大价值f[4][C],第二种情况是考虑放入a时的最大价值,即value[a]+f[4][10-weight[a]]。 原问题的解f[5][10]取上述两种情况中的最大值,即f[5][10] = max{f[4][10], (f[4][10-weight[a]+value[a]))}。 由此可以看出里面涉及到需要计算f[4][10]和f[4][10-weight[a]]即f[4][4]等子问题。 以此类推,自顶向下的分析可以看出原问题需要子问题的解,我们需要先计算出子问题的解,自底向上求解。求解方式如下表所示,顺序是自底向上、从左往右,或者从左往右、自底向上都可以。注意此问题中的abcde可以包含相同的物件,它们之间的顺序也可以是任意的,不影响最终的结果。
 

#include <iostream>
using namespace std;


int knapsack(int *W, int *V, int *res, int n, int C)
{
    int value = 0;
    int **f = new int*[n];
    for(int i = 0; i < n; i++)
    {
        f[i] = new int[C+1];
    }

    for(int i = 0; i < n; i++)
        for(int j = 0; j <= C;j++)
            f[i][j] = 0;

    for(int i = 0; i < n; i++)
    {
        f[i][0] = 0;
    }
    for(int i = 1; i <= C; i++)
    {
        f[0][i] = (i < W[0])?0:V[0];
    }
    for(int i = 1; i < n; i++)
    {
        for(int y = 1; y <= C; y++)
        {
            if(y >= W[i])
            {
                f[i][y] = (f[i-1][y] > (f[i-1][y-W[i]] + V[i]))?f[i-1][y]:(f[i-1][y-W[i]] + V[i]);
            } else {
                f[i][y] = f[i-1][y];
            }
        }
    }

    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < C+1;j++)
           cout << f[i][j] << " ";
        cout << endl;
    }

    value = f[n-1][C];
    int j = n-1;
    int y = C;
    while(j)
    {
        if(f[j][y] == (f[j-1][y-W[j]] + V[j]))
        {
            res[j] = 1;
            y = y - W[j];
        }
        j--;
    }
    if(f[0][y])
    {
        res[0] = 1;
    }

    for(int i = 0; i < n;i++)
    {
        delete f[i];
        f[i] = 0;
    }
    delete [] f;
    f = 0;
    return value;
}

void test1()
{
    int n, C;
    while(cin >> n >> C)
    {
        int *W = new int[n];
        int *V = new int[n];
        int *res = new int[n];
        for(int i = 0; i < n; i++)
        {
            res[i] = 0;
        }
        int w = 0, v = 0, i = 0;
        while(i < n)
        {
            cin >> w >> v;
            W[i] = w;
            V[i] = v;
            i++;
        }
        int value = knapsack(W, V, res, n, C);
        cout << value << endl;
        for(int i = 0; i < n; i++)
            cout << res[i] << " ";
        cout << endl;
        delete W;
        delete V;
        delete res;
    }
}

int main()
{
    test1();
    return 0;
}

参考链接:https://blog.****.net/na_beginning/article/details/62884939

 

二、132-分割回文串

 

代码:

class Solution(object):
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        if not s:
            return 0
        
        s_len = len(s)
        mem = [i for i in range(-1, s_len)]
        
        for i in range(1, s_len+1):
            for j in range(i):
                if s[j:i] == s[j:i][::-1]:
                    mem[i] = min(mem[i], mem[j] + 1)
                    
        return mem[-1]

运行结果:

训练营第七天--实战DP