• 消失之物(背包DP)(容斥或分治)


    容斥做法:

    首先n^2搞出f[i][j]第i个物品,j体积的方案数。

    去除每个物品贡献:

    设个g[i][j]表示当i不选,j体积方案数(注意不是此时的范围相对于全局,而不是1---i)

    那么我们用到一些容斥的思想

    g[i][j]=f[n][j]-g[i][j-w[i]]

    因为g[i][j-w[i]]即可表示当i选时的方案数(都是相对于全局的)

    而且注意枚举顺序,我们要用当前g[i]的状态更新之后个g[i]的状态,

    而且在j<w[i]的情况下g[i][j]=f[n][j]

    注意取模.....

     1 #include<map>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<string>
     8 #include<vector>
     9 #define MAXN 4101
    10 #define int long long
    11 using namespace std;
    12 int f[MAXN][MAXN];
    13 int g[MAXN][MAXN];
    14 int n=0,w[MAXN];
    15 int sum=0;
    16 signed main()
    17 {
    18      scanf("%lld%lld",&n,&sum);
    19      for(int i=1;i<=n;++i)
    20      {
    21          scanf("%lld",&w[i]);
    22      }
    23      f[0][0]=1;
    24      for(int i=1;i<=n;++i)
    25      {
    26         for(int j=sum;j>=0;--j)
    27         {
    28              f[i][j]=f[i-1][j];
    29         }
    30         for(int j=sum;j>=w[i];--j)
    31         {
    32              f[i][j]=(f[i][j]+f[i-1][j-w[i]]+10)%10;
    33         }
    34      }
    35      for(int i=1;i<=n;++i)
    36      {
    37          for(int j=0;j<=w[i]-1;++j)
    38          {
    39              g[i][j]=(f[n][j]+10)%10;
    40          }
    41          for(int j=w[i];j<=sum;++j)
    42          {
    43              g[i][j]=(f[n][j]-g[i][j-w[i]]+10)%10;
    44          }
    45      }
    46      for(int i=1;i<=n;++i)
    47      {
    48          for(int j=1;j<=sum;++j)
    49          {
    50               printf("%lld",(g[i][j]+10)%10);  
    51          }
    52          printf("
    ");
    53      }
    54 }
    View Code

    分治:

    %%%%skyh,非常强的思路

    我们按照分治的做法,其实每一次我们只是不选其中的一件物品,其余不变,

    那么我们利用这个性质,只用除了自身以外的物品更新当前答案

    让我们想起树的结构,把叶子节点当作询问,

    只需要每次递归左右区间,查询叶子节点时,左右都已经更新答案

    回溯时重新更新

     1 #include<iostream>
     2 #include<cstdio>
     3 #define int short
     4 using namespace std;
     5 const int N=2010;
     6 int n,m,w[N],dp[15][N];
     7 inline void add(int &a,int b){
     8     a+=b;
     9     if(a>=10) a-=10;
    10 }
    11 void solve(int dep,int l,int r){
    12     if(l==r){
    13         for(int i=1;i<=m;++i) printf("%hd",dp[dep-1][i]);
    14         puts("");
    15         return ;
    16     }
    17     int mid=l+r>>1;
    18     for(int i=0;i<=m;++i) dp[dep][i]=dp[dep-1][i];
    19     for(int i=mid+1;i<=r;++i) for(int j=m;j>=w[i];--j) add(dp[dep][j],dp[dep][j-w[i]]);
    20     solve(dep+1,l,mid);
    21     for(int i=0;i<=m;++i) dp[dep][i]=dp[dep-1][i];
    22     for(int i=l;i<=mid;++i) for(int j=m;j>=w[i];--j) add(dp[dep][j],dp[dep][j-w[i]]);
    23     solve(dep+1,mid+1,r);
    24 }
    25 signed main(){
    26     scanf("%hd%hd",&n,&m);
    27     for(int i=1;i<=n;++i) scanf("%hd",&w[i]);
    28     dp[0][0]=1; solve(1,1,n);
    29     return 0;
    30 }
    %%%skyh
  • 相关阅读:
    java实现第四届蓝桥杯梅森素数
    java实现第四届蓝桥杯连号区间数
    java实现第四届蓝桥杯连号区间数
    java实现第四届蓝桥杯连号区间数
    java实现第四届蓝桥杯连号区间数
    java实现第四届蓝桥杯连号区间数
    java实现第四届蓝桥杯带分数
    【Java-加密算法】对称加密、非对称加密、单向散列(转)
    rsa加解密的内容超长的问题解决
    install4j的使用
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11276545.html
Copyright © 2020-2023  润新知