其他分享
首页 > 其他分享> > 1058 Min酱要旅行 01背包变式 递推求方案数

1058 Min酱要旅行 01背包变式 递推求方案数

作者:互联网

链接:https://ac.nowcoder.com/acm/problem/210520
来源:牛客网

题目描述

从前有个富帅叫做Min酱,他很喜欢出门旅行,每次出门旅行,他会准备很大一个包裹以及一大堆东西,然后尝试各种方案去塞满它。
然而每次出门前,Min酱都会有个小小的烦恼。众所周知,富帅是很讨妹子喜欢的,所以Min酱也是有大把大把的妹子,每次出门都会有一只妹子随行。然而这些妹子总是会非常排斥Min酱准备的众多东西中的一件(也许是因为这件东西是其它妹子送给Min酱的),这件东西Min酱是万万不敢带上的,否则的话……嘿嘿嘿。另外,妹子们嫌Min酱的包裹太丑了,会自带一个包裹去换掉Min酱的包裹。
Min酱是个控制欲很强的人,然而这样一来,Min酱就不知道可以用多少种方案去填充包裹了,所以Min酱很郁闷。
于是Min酱找到了聪明的你,希望你能帮助他解决这些问题。
另外,Min酱是个典型的懒人,他不希望每次带不同的妹子出去都麻烦你,所以他希望你能给出有K1..KnK_1..K_nK1​..Kn​ 件物品,第 i\ i i 件不能带并且包裹大小为  1..M\ 1..M 1..M 的所有方案数。

输入描述:

可能有多组数据。对于每一组数据:
第一行,两个整数  n,m\ n,m n,m,分别表示物品数量和妹子带的包裹的最大容积。
第二行, n\ n n 个正整数,分别表示物品 KiK_iKi​ 的体积。

 

输出描述:

对于每一组数据,输出一个 n×mn \times mn×m 的矩阵,第  i\ i i 行  j\ j j 列表示包裹容积为  j\ j j ,不能带 i\ i i 号物品时,装满包裹的方案总数。
为了美观起见,我们只保留方案数的个位。
示例1

输入

复制
3 2
1 1 2

输出

复制
11
11
21

备注:

1≤n,m≤2300,Ki≤10001\leq n,m \leq 2300,K_i \leq 10001≤n,m≤2300,Ki​≤1000

分析

递推求方案数的问题,问不选择某个数在某个体积的时候的方案数。

按照一般的思路,先把所有的方案数求出来 再减去 选择某个数的时候的方案数 就是答案

如何求出选择某个物品的方案数呢?

由01背包压缩体积后的方程可知,dp[j] 表示的是选择体积j 时候的方案数

那么当 j < a[i] 的时候。dp[j] 表示的就是不选择 a[i] 的时候的方案数

设 g[j] 表示不选择 i 的体积为j 的时候的方案数,有状态转移方程式

g[j] = dp[j] (j < a[i])

g[j] = dp[j] - g[j - a[i]];

//-------------------------代码----------------------------

//#define int ll
const int N = 1e5+10;
int n,m;
int a[N];
int f[N],g[N];
void solve()
{
    ms(f,0);
    cin>>n>>m;
    fo(i,1,n) cin>>a[i];
    f[0] = 1;
    fo(i,1,n) {
        of(j,m,a[i]) {
            f[j]=(f[j]+f[j-a[i]])%10;
        }
    }
    fo(i,1,n) {
        fo(j,0,m) {
            if(j<a[i])g[j] = f[j]; 
            else g[j] =(( f[j] - g[j-a[i]]) + 10 )  % 10;
        }
        fo(j,1,m) {
            cout<<g[j];
        }cout<<endl;
    }
}

signed main(){
    clapping();TLE;
    
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

标签:方案,01,变式,..,Min,int,包裹,妹子
来源: https://www.cnblogs.com/er007/p/16508428.html