Zoj 3164 Cookie Choice(다중 가방 + 그룹 가방, 업데이트 대기열 최적화)
Time Limit: 2 Seconds
Memory Limit: 32768 KB
MM enjoyed cookies very much. On Saint Valentine's Day, when she stepped into a big cookie store again, she wouldn't leave unless DD spent all his money in pocket!
There are N kinds of cookies, labeled from 1 to N, and all can be bought without any restriction by the store. But actually, for some kinds of cookies, MM wanted to buy one piece at most, and for some kinds of cookies, MM wanted to buy Ki pieces at most, and for some other kinds of cookies, there didn't exist an upper bound that MM wanted to buy.
There is another requirement from MM: there are some groups of cookies, MM considered their tastes similar, so she wanted to buy at most one kind of cookies in each group. A kind of cookie wouldn't appear in more than one group.
For the ith kind of cookies, MM has an "enjoyable value" Ei, if DD bought Ai pieces of this kind for her, and Ai didn't exceed her upper bound, MM get EiAi of enjoyable value. After buying cookies, MM's total enjoyable value will be the sum of EiAi.
But actually, poor DD had only D dollars, and the price for the ith kind of cookies is Pi dollars per piece. DD must spend all his Ddollars to buy cookies, to meet requirements about amount and taste from MM, and to make MM's enjoyable value as high as possible. What's more, as you know, a legal plan's enjoyable value must be non-negative.
Input
There are multiple test cases. Each test case consists of three parts.
The first part is one line with two integers N and D.
The second part has N lines, line i consists of three integers Ki, Ei and Pi. If Ki equals to 0, it means for ith kind of cookies, there didn't exist an upper bound that MM wanted to buy, otherwise Ki is the upper bound for ith kind of cookies.
The third part describes the groups. A non-negative integer G represents the number of groups, and then G lines, each line consists of some integers represents labels of kinds of cookies in this group.
One blank line between test cases.
Output
If the proper and optimal plan exists, output the maximal total enjoyable value ΣEiAi, otherwise output "i'm sorry...".
Output one line per text case.
Data Restriction 1 <=
N <= 1024, 0 <=
D <= 1024.
0 <=
Ki <= 1024, -1024 <=
Ei <= 1024, 0 <
Pi <=
D.
0 <=
G <= 8.
All numbers referred are integers.
Number of test cases is no more than 80.
Sample Input
2 1024
0 1 3
0 0 1
0
10 1023
1 1 1
1 1 2
1 1 4
1 1 8
1 1 16
1 1 32
1 1 64
1 1 128
3 -1 256
1 1 512
1
9 10
10 1023
1 1 1
1 1 2
1 1 4
1 1 8
1 1 16
1 1 32
1 1 64
1 1 128
1 1 256
1 1 512
1
9 10
Sample Output
341
5
i'm sorry...
Author: CUI, Tianyi
Source: ZOJ Monthly, February 2009
제목:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3164
분석: 이 문제는 배낭 9강 저자 최천익이 낸 문제입니다. 이 문제는 매우 복잡한 배낭 문제입니다. 그 안에 다중 배낭을 사용하면 사상을 배가시키고 배낭을 나눈다...
좀 느리게 썼어, 최적화하기 귀찮아.
2012-9-26 어젯밤에 09년 xch의 논문을 봤는데 가방의 각종 최적화에 대해 새로운 이해를 얻었고 이 문제를 골랐습니다. 다중 가방의 대기열 최적화, 그리고 범용 물품의 합병 최적화, 즉 그룹 가방의 최적화를 사용했습니다. 바로rank1에 도착했습니다. 하하 코드는 뒤에 있습니다.
코드:
#include<cstdio>
#include<iostream>
using namespace std;
const int mm=1111;
const int lm=-10000000;
int f[mm],tmp[mm],s[mm],e[mm],p[mm],t[mm],w[9][mm];
int i,j,k,v,l,r,n,d,g;
bool get(int g)
{
int a,b;
while(((b=getchar())<'0'||b>'9')&&b!='
');
if(b=='
')return 0;
for(a=0;b>='0'&&b<='9';b=getchar())a=a*10+b-'0';
t[a-1]=g;
return b!='
';
}
void clear(int f[])
{
for(int i=1;i<=d;++i)f[i]=-1000000000;
f[0]=0;
}
void CompletePack(int v,int e,int f[])
{
for(int i=v;i<=d;++i)f[i]=max(f[i],f[i-v]+e);
}
void ZeroOnePack(int v,int e,int f[])
{
for(int i=d;i>=v;--i)f[i]=max(f[i],f[i-v]+e);
}
int main()
{
while(scanf("%d%d",&n,&d)!=-1)
{
for(i=0;i<n;++i)scanf("%d%d%d",&s[i],&e[i],&p[i]),t[i]=0;
scanf("%d",&g);
for(getchar(),i=1;i<=g;++i)while(get(i));
for(i=1;i<=g;++i)clear(w[i]);
clear(f);
for(i=0;i<n;++i)
{
if(t[i])clear(tmp);
if(!s[i]||s[i]*p[i]>=d)CompletePack(p[i],e[i],t[i]?tmp:f);
else
{
j=1;
while(j<s[i])
{
ZeroOnePack(p[i]*j,e[i]*j,t[i]?tmp:f);
s[i]-=j;
j<<=1;
}
ZeroOnePack(p[i]*s[i],e[i]*s[i],t[i]?tmp:f);
}
if(t[i])for(j=1;j<=d;++j)w[t[i]][j]=max(w[t[i]][j],tmp[j]);
}
for(k=1;k<=g;++k)
for(i=d;i>=0;--i)
for(j=1;j<=i;++j)
if(f[i-j]>lm&&w[k][j]>lm)
f[i]=max(f[i],f[i-j]+w[k][j]);
if(f[d]>=0)printf("%d
",f[d]);
else puts("i'm sorry...");
}
return 0;
}
코드 2:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int mm=1111;
int f[mm],f1[mm],f2[mm],t[mm],e[mm],p[mm],s[mm],id[mm],q[mm],qw[mm];
int i,j,k,n,d,g;
bool get(int g)
{
int a,b;
while((b=getchar())<'0'||b>'9');
for(a=0;b>='0'&&b<='9';b=getchar())a=a*10+b-'0';
t[a-1]=g;
return (b!='
');
}
bool cmp(int a,int b)
{
return t[a]<t[b];
}
void CompletePack(int e,int p)
{
for(int i=0;i<=d;++i)f2[i]=f1[i];
for(int i=p;i<=d;++i)
{
f2[i]=max(f2[i],f2[i-p]+e);
f[i]=max(f[i],f2[i]);
}
}
void MultiPack(int s,int e,int p)
{
int i,j,k,l,r,now,m;
for(i=0;i<p;++i)
for(m=(d-i)/p,j=l=0,r=-1;j<=m;++j)
{
now=f1[k=j*p+i]-j*e;
while(l<=r&&qw[r]<=now)--r;
q[++r]=j,qw[r]=now;
if(j-q[l]>s)++l;
f[k]=max(f[k],qw[l]+j*e);
}
}
int main()
{
while(~scanf("%d%d",&n,&d))
{
for(i=0;i<n;++i)
t[i]=0,id[i]=i,scanf("%d%d%d",&s[i],&e[i],&p[i]);
scanf("%d",&g);
for(i=1;i<=g;++i)while(get(i));
sort(id,id+n,cmp);
for(i=0;i<=d;++i)f1[i]=f[i]=-1e8;
f1[0]=f[0]=0;
for(i=0;i<n;++i)
{
k=id[i];
if(!s[k]||s[k]*p[k]>=d)CompletePack(e[k],p[k]);
else MultiPack(s[k],e[k],p[k]);
if(!t[k]||t[k]!=t[id[i+1]])
for(j=0;j<=d;++j)f1[j]=f[j];
}
if(f[d]>=0)printf("%d
",f[d]);
else puts("i'm sorry...");
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
깨끗한 것을 보고 싶기 때문에 최적화 함수의 벤치마크에 이용되는 함수의 가시화를 해 보았다결정되지 않음 (자기 만족) 「헤이 이런 거 있어」라고 생각하는 사람 최적화 함수란? 거친 이미지로 1) x + 10 = 25 2) x + 60 = 15 3) x + 45 = 60 의 x를 기계에 구할 때 정확하게 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.