题解 P1450 【[HAOI2008]硬币购物】

本题想到多重背包还是很容易的(什么?不知道多重背包?)
但是,另一题解已经将时间安排计算地明明白白
所以想到完全背包(多重背包跟01背包似乎区别不大)
可以先预处理完全背包的情况,然后瞎搞容斥原理
不懂容斥原理的看这里:传送门
想到完全背包容斥原理后,剩下的就只是打表一些简单的实现了
上代码


#include<bits/stdc++.h>
using namespace std;
long long c[5],d[5],dp[100010],tot,s;
long long Q(long long x)//便于打表
{
	return c[x]*(d[x]+1);
}
int main()
{
	for(int i=1;i<=4;i++)
	{
		cin>>c[i];
	}
	cin>>tot;
	dp[0]=1;//初始化,之后预处理
	for(int i=1;i<=4;i++)
	{
		for(int j=c[i];j<=100001;j++)
		{
			dp[j]+=dp[j-c[i]];
		}
	}
	for(int js=1;js<=tot;js++)
	{
		for(int i=1;i<=4;i++)
		{
			cin>>d[i];
		}
		cin>>s;
		long long ans=dp[s];//初始,之后容斥原理代码
		if(s>=Q(1))
			ans-=dp[s-Q(1)];
		if(s>=Q(2))
			ans-=dp[s-Q(2)];		
		if(s>=Q(3))
			ans-=dp[s-Q(3)];
		if(s>=Q(4))
			ans-=dp[s-Q(4)];
		if(s>=Q(1)+Q(2))
			ans+=dp[s-Q(1)-Q(2)];
		if(s>=Q(1)+Q(3))
			ans+=dp[s-Q(1)-Q(3)];
		if(s>=Q(1)+Q(4))
			ans+=dp[s-Q(1)-Q(4)];
		if(s>=Q(2)+Q(3))
			ans+=dp[s-Q(2)-Q(3)];
		if(s>=Q(2)+Q(4))
			ans+=dp[s-Q(2)-Q(4)];
		if(s>=Q(3)+Q(4))
			ans+=dp[s-Q(3)-Q(4)];
		if(s>=Q(1)+Q(2)+Q(3))
			ans-=dp[s-Q(1)-Q(2)-Q(3)];
		if(s>=Q(1)+Q(2)+Q(4))
			ans-=dp[s-Q(1)-Q(2)-Q(4)];
		if(s>=Q(1)+Q(3)+Q(4))
			ans-=dp[s-Q(1)-Q(3)-Q(4)];
		if(s>=Q(2)+Q(3)+Q(4))
			ans-=dp[s-Q(2)-Q(3)-Q(4)];
		if(s>=Q(1)+Q(2)+Q(3)+Q(4))
			ans+=dp[s-Q(1)-Q(2)-Q(3)-Q(4)];//个人认为这个表打得相当美观~
		cout<<ans<<endl;
	}
} 
posted @ 2019-02-02 21:59  G_A_TS  阅读(476)  评论(0)    收藏  举报