zoukankan      html  css  js  c++  java
  • P1077摆花

    传送

    总共要摆m盆花,而每种花最多有a[i]盆。仔细思索,发现它是一个多重背包求方案数问题。但是我蒟蒻的不会,于是跑去问大佬。

    以下状态转移方程及化简from rqy

    如果第i个物品有a[i],每个的体积是b[i],设f[i][j]为前i个物品占用体积为j的空间的方案数

    则:f[i][j]=f[i-1][j]+f[i-1][j-b[i]]+f[i-1][j-2*b[i]]+………………+f[i-1][j-a[i]*b[i]]   (f[i][j]可以由f[i-1][j]什么都不选得来,可以由f[i-1][j-b[i]]再选一个第i种物品得来……)

    运用到这个题里,显然每盆花的体积是1,状态转移方程就是:

    f[i][j]=f[i-1][j]+f[i-1][j-1]+f[i-1][j-2]+..........+f[i-1][j-a[i]]

    看到这里,我们就可以写出三层循环的代码了

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,a[105];
    long long f[105][105];
    const int mod=1000007;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
          scanf("%d",&a[i]);
        f[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=m;j++)//注意循环顺序
            {
              for(int k=0;k<=min(j,a[i]);k++)
              {
               f[i][j]+=f[i-1][j-k];
               f[i][j]=(f[i][j]+mod)%mod;
              }
            }
        }
        printf("%d",(f[n][m]+mod)%mod);
    }

    这样就可以ac了

    但是这个方程很长有木有,看起来好像可以化简有木有

    对比f[i][j-[b[i]]=f[i-1][j-b[i]]+f[i-1][j-2*b[i]]+......+f[i-1][j-b[i]-(a[i]-1)*b[i]]+f[i-1][j-b[i]-a[i]*b[i]]

    发现f[i][j]=f[i-1][j]+f[i][j-b[i]]-f[i-1][j-(a[i]+1)*b[i]]

    amazing!

    那这个化简后的方程怎么理解呢?

    这就相当于说f[i][j]要么从f[i-1][j]一盆第i种花也不选,直接推过来,要么第i种已经选了1盆了,再来一盆第i种(f[i][j-b[i]]),但是如果你第i种已经选了ai盆了,就不能再继续选了,所以要把选了ai盆后再选的方案数减掉(因为选ai盆是合法的,而选ai+1盆才是不合法的,所以是减f[i-1][j-(a[i]+1)*b[i]])

    但是蒟蒻懒得不会打代码qwq

  • 相关阅读:
    架设证书服务器 及 让IIS启用HTTPS服务
    实验二. 使用LoadRunner进行压力测试
    loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写
    康威定律,可以学习一下
    各国iPhone5系列最新裸机价格
    .yml是什么文件
    win32多线程程序设计笔记(第五章)
    kvm libvirt: hostdev passthrough support 解决加密狗冲突问题
    九度OnlineJudge之1023:EXCEL排序
    [置顶] Android开发之XML文件的解析
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/11043664.html
Copyright © 2011-2022 走看看