P1164 小A点菜

P1164 小A点菜

题意

给你一个空间为 m 的背包,有 n 件物品,第 i 件物品所占的空间为 vi,求恰好装满的方案个数。

思路

这就是一个简单的背包问题,可惜我wa 了大半天,看了题解才明白到的是哪里出现了错误-····哎好菜

二维题解

#include
using namespace std;
const int Len = 1005;
int n,m;
int dp[Len][Len * 10];

int main()
{
//    freopen("T.txt","r",stdin);
    scanf("%d %d", &n, &m);
    for(int i = 0; i <= n; i ++)    //⚠️1。这个特殊的初始,当j = 0 背包空间为0的时候,从该状态转移到别的状态适合发的,因为这个时候背包的空间恰好用完
        dp[i][0] = 1;
    int v;
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d", &v);
        for(int j = 1; j <= m; j ++)  //⚠️。这里要从j = 1的时候开始讨论,即背包空间为1的时候开始,虽然 j < v 的时候装不下当前的物品,但是当前的背包空间j是有可能装下之前的物品的
        {
            dp[i][j] += dp[i - 1][j];
            if(j >= v)
            dp[i][j] += dp[i - 1][j - v];
        }
    }
    printf("%d",dp[n][m]);

    return 0;
}

一维题解

#include
using namespace std;
const int Len = 10005;
int n,m;
int dp[Len];

int main()
{
//    freopen("T.txt","r",stdin);
    scanf("%d %d", &n, &m);
    dp[0] = 1; 	//⚠️这里的由于这里的一维dp数组的空间重复利用,初始化一个就行了
    int v;
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d", &v);
        for(int j = m; j >= v; j --)	//⚠️这里也是一维dp空间的重复利用,从而免去了在二维dp数组的情况下的从j = 1 开始讨论。!!
        {
            dp[j] += dp[j - v];
        }
    }
    printf("%d",dp[m]);

    return 0;
}

你可能感兴趣的:(#,背包九讲)