动态规划专题之zoj1013

来源:互联网 发布:网络电影播放器排行榜 编辑:程序博客网 时间:2024/05/19 20:43

 //zoj动态规划 1031
//由于要求有多个背包,所以先找到背包与背包间的关系
//用dp[i][j][k]来表示前i层的当总量分别是j,k时k的最大值
//此时枚举第i+1层的情况,并与前i层的各种情况组合,得到新的情况表格
//最后只要遍历最新一层的即可
//我的费劲点:(1)多组数据忘记初始化
//            (2)min函数写的时候少写一个
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int state[2][510][510];
struct Equit
{
int w;
int s;
int p;
}e[3];
int c1,c2,c3,d;
int Min(int a,int b)
{
return a<b?a:b;
}
int Max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int T;
int nmax;
int i,j,k,l;
int z1,z2;
int W,S;
int p,q;
int n;
T=0;
//freopen("in.txt","r",stdin);
while(~scanf("%d",&n)&&n)
{
        if(T)
printf("\n");
for(i=0;i<3;i++)
{
scanf("%d%d%d",&e[i].w,&e[i].s,&e[i].p);
}
scanf("%d%d%d%d",&c1,&c2,&c3,&d);
memset(state,-1,sizeof(state));
state[0][0][0]=0;
p=0;q=1;//类似于滚动数组的方式
for(i=0;i<n;i++)
{
memset(state[q],-1,sizeof(state[q]));
scanf("%d%d",&W,&S);
for(j=0;j*e[0].w<=W && j*e[0].s<=S;j++)//第i层的枚举
{
for(k=0;(j*e[0].w+k*e[1].w)<=W && (j*e[0].s+k*e[1].s)<=S;k++)
{
int t=Min((W-(j*e[0].w+k*e[1].w))/e[2].w,(S-(j*e[0].s+k*e[1].s))/e[2].s);
for(z1=0;z1<=500;z1++)
{
for(z2=0;z2<=500;z2++)
{
if(state[p][z1][z2]==-1)
       continue;
//当新的安排情况大于原来到达过的情况时,更新
state[q][z1+j][z2+k]=Max(state[q][z1+j][z2+k],state[p][z1][z2]+t);
}
}
}
}
int t=q;
q=p;
p=t;
}
int ans=-1;
for(i=0;i<=500;i++)
{
for(j=0;j<=500;j++)
{
if(state[p][i][j]==-1) continue;
int k=state[p][i][j];
    int power=i*e[0].p+j*e[1].p+k*e[2].p;
    int minni=Min(Min(i/c1,j/c2),k/c3);//大傻逼啊
if(minni<0)
minni=0;
    power+=minni*(d-c1*e[0].p-c2*e[1].p-c3*e[2].p);
    ans=Max(power,ans);
}
}
printf("Case %d: %d\n",++T,ans);

}
return 0;
}
0 0
原创粉丝点击