zoukankan      html  css  js  c++  java
  • 硬币购物

    如果是背包的话

    这个时间复杂度不对

    所以是容斥????

    直接计算方案数不好计算,所以考虑补集转化,总共的方案数可以用完全背包预处理,就是设f[0]=1,以后不断+=就可以了,

    那么不合法的方案呢,就是某些物品超出了数量限制。有可能一个超出限制,也有可能两个超出限制,所以是容斥

    因为四个物品价值数量都不同,所以应该分开讨论

    一个超出的有四种

    两个超出的有六种......

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn=1e5+7;
     8 typedef long long ll;
     9 ll t,s;
    10 ll c[7],d[7],f[maxn];
    11 int main(){
    12   cin>>c[1]>>c[2]>>c[3]>>c[4]>>t;
    13   f[0]=1;
    14   for(int i=1;i<=4;i++)
    15     for(int j=c[i];j<=maxn-5;j++)
    16       f[j]+=f[j-c[i]];
    17   while(t--){
    18     cin>>d[1]>>d[2]>>d[3]>>d[4]>>s;
    19     ll ret=f[s];
    20     if(s>=(d[1]+1)*c[1]) ret-=f[s-(d[1]+1)*c[1]];
    21     if(s>=(d[2]+1)*c[2]) ret-=f[s-(d[2]+1)*c[2]];
    22     if(s>=(d[3]+1)*c[3]) ret-=f[s-(d[3]+1)*c[3]];
    23     if(s>=(d[4]+1)*c[4]) ret-=f[s-(d[4]+1)*c[4]];
    24     if(s>=(d[1]+1)*c[1]+(d[2]+1)*c[2]) ret+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]];
    25     if(s>=(d[1]+1)*c[1]+(d[3]+1)*c[3]) ret+=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]];
    26     if(s>=(d[1]+1)*c[1]+(d[4]+1)*c[4]) ret+=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]];
    27     if(s>=(d[2]+1)*c[2]+(d[3]+1)*c[3]) ret+=f[s-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
    28     if(s>=(d[2]+1)*c[2]+(d[4]+1)*c[4]) ret+=f[s-(d[2]+1)*c[2]-(d[4]+1)*c[4]];
    29     if(s>=(d[3]+1)*c[3]+(d[4]+1)*c[4]) ret+=f[s-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
    30     if(s>=(d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[3]+1)*c[3]) ret-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
    31     if(s>=(d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[4]+1)*c[4]) ret-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[4]+1)*c[4]];
    32     if(s>=(d[1]+1)*c[1]+(d[3]+1)*c[3]+(d[4]+1)*c[4]) ret-=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
    33     if(s>=(d[2]+1)*c[2]+(d[3]+1)*c[3]+(d[4]+1)*c[4]) ret-=f[s-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
    34     if(s>=(d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[3]+1)*c[3]+(d[4]+1)*c[4])
    35       ret+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
    36     cout<<ret<<endl;
    37   } 
    38 }

    还有一种更加简单的,可以用二进制数来枚举哪些物品超出了限制:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long ll;
     8 const int maxn=1e5+7;
     9 ll c[7],d[7],f[maxn];
    10 ll t,s,ans;
    11 int main(){
    12   cin>>c[1]>>c[2]>>c[3]>>c[4]>>t;
    13   f[0]=1;
    14   /*for(ll i=1;i<=maxn-5;i++)
    15     for(ll j=1;j<=4;j++)
    16       if(i>=c[j]) f[i]+=f[i-c[j]];*/
    17   for(int i=1;i<=4;i++)
    18     for(int j=c[i];j<=maxn-5;j++)
    19       f[j]+=f[j-c[i]];
    20   while(t--){
    21     cin>>d[1]>>d[2]>>d[3]>>d[4]>>s;
    22     ans=0;
    23     for(ll i=0;i<=15;i++){
    24       ll ret=s,cnt=0;
    25       for(ll j=1;j<=4;j++){
    26         if((i>>(j-1))&1){
    27           cnt^=1;ret-=c[j]*(d[j]+1);
    28         }
    29       }
    30       if(ret<0) continue;
    31       if(cnt) ans-=f[ret];
    32       else ans+=f[ret];
    33     }
    34     cout<<ans<<endl;
    35   }
    36 } 

    背包的枚举顺序啊

  • 相关阅读:
    Ajax
    通过浏览器渲染过程来进行前端优化
    渲染树结构、布局和绘制
    JS 和 CSS 的位置对其他资源加载顺序的影响
    Linq中dbSet 的查询
    如何在windows“我的电脑”中添加快捷文件夹
    SQL Server中2008及以上 ldf 文件过大的解决方法
    出现“初始化数据库时发生异常”解决办法
    MVC使用ajax取得JSon数据
    asp.net mvc 使用Ajax调用Action 返回数据【转】
  • 原文地址:https://www.cnblogs.com/lcan/p/9901707.html
Copyright © 2011-2022 走看看