zoukankan      html  css  js  c++  java
  • 洛谷P1450 [HAOI2008]硬币购物 背包+容斥

    无限背包+容斥?


    观察数据范围,可重背包无法通过,假设没有数量限制,利用用无限背包

    进行预处理,因为实际硬币数有限,考虑减掉多加的部分

    如何减?利用容斥原理,减掉不符合第一枚硬币数的,第二枚,依次类推

    加上不符第一枚和第二枚的方案,第一枚和第三枚的方案以此类推,不明

    白原理可以去看一下容斥原理

    较长代码(懒得优化)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #define ll long long
    using namespace std;
    const int maxn=1e5+10;
    inline int read(){
    	int ret=0;
    	int f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-')
    			f=-f;
    		ch=getchar();
    	}
    	while(ch<='9'&&ch>='0'){
    		ret=ret*10+(ch^'0');
    		ch=getchar();
    	}
    	return f*ret;
    }
    int c[5];
    ll s;
    ll dp[maxn];
    int n;
    ll ans;
    ll d[5];
    ll getn(int x){
    	return (d[x]+1)*c[x];
    } 
    int main(){
    //	freopen("a.txt","r",stdin);
    	for(int i=1;i<=4;i++){
    	//	c[i]=read();
    	    cin>>c[i];
    	}
    	   cin>>n;
    //	n=read();
    //	cout<<n;
    	dp[0]=1;
    //	cout<<dp[-10]<<endl;
    	for(int i=1;i<=4;i++){
    		for(int j=c[i];j<=maxn;j++){
    			dp[j]+=dp[j-c[i]];
    		}
    	}
    //	cout<<dp[10]<<endl;
    	while(n){
    		n--;
    		for(int i=1;i<=4;i++){
    			//d[i]=read();
    			cin>>d[i];
    		}
    	//	s=read();
    	    cin>>s;
    		ans=dp[s];
    		for(int i=1;i<=4;i++){
    			if(s>=getn(i)){
    				ans-=dp[s-getn(i)];	
    			}
    		}
    		if(s>=getn(1)+getn(2)){
    			ans+=dp[s-getn(1)-getn(2)];
    		}
    		if(s>=getn(2)+getn(3)){
    			ans+=dp[s-getn(2)-getn(3)];
    		}
    		if(s>=getn(3)+getn(4)){
    			ans+=dp[s-getn(3)-getn(4)];
    		}
    		if(s>=getn(1)+getn(4)){
    			ans+=dp[s-getn(1)-getn(4)];
    		}
    		if(s>=getn(2)+getn(4)){
    			ans+=dp[s-getn(4)-getn(2)];
    		}
    		if(s>=getn(1)+getn(3)){
    			ans+=dp[s-getn(1)-getn(3)];
    		}
    		if(s>=getn(1)+getn(2)+getn(3)){
    			ans-=dp[s-getn(1)-getn(2)-getn(3)];
    		}
    		if(s>=getn(1)+getn(2)+getn(4)){
    			ans-=dp[s-getn(1)-getn(2)-getn(4)];
    		}
    		if(s>=getn(1)+getn(3)+getn(4)){
    			ans-=dp[s-getn(1)-getn(3)-getn(4)];
    		}
    		if(s>=getn(4)+getn(2)+getn(3)){
    			ans-=dp[s-getn(4)-getn(2)-getn(3)];
    		}
    		if(s>=getn(1)+getn(2)+getn(3)+getn(4)){
    			ans+=dp[s-getn(1)-getn(2)-getn(3)-getn(4)];
    		}
    		cout<<ans<<endl;
    	}		
    	return 0;
    } 
    

    完结撒花

  • 相关阅读:
    UIView的clipsToBounds属性,layoutSubViews及触摸事件传递(默认情况下)总结
    ISO中运行时简单使用及KVC补充
    IOS中UISearchBar的使用
    oc的block
    oc的协议(protocol)
    oc的分类category
    oc内存的理解
    oc笔记(转载)
    oc对象中属性总结
    servlet,struts1,struts2,spring
  • 原文地址:https://www.cnblogs.com/rpup/p/13795803.html
Copyright © 2011-2022 走看看