【USACO题库】3.3.2 Shopping Offers商店购物

这题我打的真的是千辛万苦啊!!!
先打了个贪心,呵呵WA50。。。
然后知道有一个五维DP的方法(真的是简单易懂)

设f[i][j][k][l][v]表示

第一个还剩i个
第二个还剩j个
第三个还剩k个
第四个还剩l个
第五个还剩v个

看看吧,真多啊

接着暴力转移n个(记得判一下能否转移)
每次转移的时候都看看将它剩下的全部单价购买后的价钱能否影响ans

#include<cstdio>
#include<cstring>
#include<algorithm>
#define minn(x,y) x=x<y ? x:y
#define fd f[d[1]][d[2]][d[3]][d[4]][d[5]]
using namespace std;
int n,m,a[101],b[101][6][2],d[6],e[6];
int fr[1001],c[101],nd[6],sl[6],ans=66666666;
int f[6][6][6][6][6];
bool bz;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

int main()
{
	freopen("shop.in","r",stdin);
//	freopen("shop.out","w",stdout);
	n=read();
	for (int i=1;i<=n;i++)
	{
		a[i]=read();
		for (int j=1;j<=a[i];j++)
			b[i][j][0]=read(),b[i][j][1]=read();
		c[i]=read();
	}
	m=read();
	for (int i=1;i<=m;i++)
		fr[read()]=i,nd[i]=read(),sl[i]=read();
	for (int i=1;i<=n;i++)
		for (int j=1;j<=a[i];j++)
			b[i][j][0]=fr[b[i][j][0]];
	memset(f,5,sizeof(f));
	f[nd[1]][nd[2]][nd[3]][nd[4]][nd[5]]=0;
	for (d[1]=nd[1];d[1]>=0;d[1]--)
		for (d[2]=nd[2];d[2]>=0;d[2]--)
			for (d[3]=nd[3];d[3]>=0;d[3]--)
				for (d[4]=nd[4];d[4]>=0;d[4]--)
					for (d[5]=nd[5];d[5]>=0;d[5]--)
					{
						for (int w=1;w<=n;w++)
						{
							bz=1;
							memcpy(e,d,sizeof(d));
							for (int o=1;o<=a[w];o++)
								if (e[b[w][o][0]]<b[w][o][1]) {bz=0; break;}
								else e[b[w][o][0]]-=b[w][o][1];
							if (!bz) continue;
							minn(f[e[1]][e[2]][e[3]][e[4]][e[5]],fd+c[w]);
						}
						 ans=min(ans,fd+d[1]*sl[1]+d[2]*sl[2]+d[3]*sl[3]+d[4]*sl[4]+d[5]*sl[5]);
					}
	printf("%d
",ans);
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817699.html