您的位置:首页 > 其它

HDU 3182 Hamburger Magi(状压DP)

2018-01-27 11:25 302 查看

Hamburger Magi

[b]Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1109    Accepted Submission(s): 414
[/b]

[align=left]Problem Description[/align]
In the mysterious forest, there is a group of Magi. Most of them like to eat human beings, so they are called “The Ogre Magi”, but there is an special one whose favorite food is hamburger, having been jeered by the others
as “The Hamburger Magi”.

Let’s give The Hamburger Magi a nickname “HamMagi”, HamMagi don’t only love to eat but also to make hamburgers, he makes N hamburgers, and he gives these each hamburger a value as Vi, and each will cost him Ei energy, (He can use in total M energy each day).
In addition, some hamburgers can’t be made directly, for example, HamMagi can make a “Big Mac” only if “New Orleams roasted burger combo” and “Mexican twister combo” are all already made. Of course, he will only make each kind of hamburger once within a single
day. Now he wants to know the maximal total value he can get after the whole day’s hard work, but he is too tired so this is your task now!

 

[align=left]Input[/align]
The first line consists of an integer C(C<=50), indicating the number of test cases.

The first line of each case consists of two integers N,E(1<=N<=15,0<=E<=100) , indicating there are N kinds of hamburgers can be made and the initial energy he has.

The second line of each case contains N integers V1,V2…VN, (Vi<=1000)indicating the value of each kind of hamburger.

The third line of each case contains N integers E1,E2…EN, (Ei<=100)indicating the energy each kind of hamburger cost.

Then N lines follow, each line starts with an integer Qi, then Qi integers follow, indicating the hamburgers that making ith hamburger needs.
 

[align=left]Output[/align]
For each line, output an integer indicating the maximum total value HamMagi can get.
 

[align=left]Sample Input[/align]

1
4 90
243 464 307 298
79 58 0 72
3 2 3 4
2 1 4
1 1
0

 

[align=left]Sample Output[/align]

298

 

题意:

给你n个汉堡,每一个汉堡有价值Vi和制作做需要的能量消耗Ei,你有总共的能量E,问你用你的能量最大可以获得的价值是多少

并且这里每一个汉堡有制作的前提,有一些汉堡需要其他汉堡制作完成之后才能制作

解析:

这里各个点不要求排列的顺序,所以只需要一维的dp表示状态

DP[i]表示在状态i下最大的价值

DP[i|(1<<(j-1))]=max{dp[i|(1<<(j-1))],dp[i]+value[j]]}

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 20;
const int SMAX= 1<<16;
int cost[MAXN];
int value[MAXN];
int fronts[MAXN];
int dp[SMAX];

int main()
{
int t;
int n,c;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++)
{
scanf("%d",&value[i]);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&cost[i]);
}
int num;
for(int i=1;i<=n;i++)
{
scanf("%d",&num);
int tmp;
fronts[i]=0;
for(int j=1;j<=num;j++)
{
scanf("%d",&tmp);
fronts[i]=fronts[i]|(1<<(tmp-1));
}
}
memset(dp,-1,sizeof(dp));
dp[0]=0;  //用于初始情况下,将所有不需要前提的汉堡加进去
int ans=0;
for(int i=0;i<(1<<n);i++)  //正着搜
{
for(int j=1;j<=n;j++) //将j加入
{
if(dp[i]==-1) continue;  //关键,因为这里是从前往后遍历的,汉堡的前提就能体现在这里
//类似于拓扑排序,先将没有前提的点放进去,在通过这些点延生,并且延生的条件当前点的前提都已经做好了(并且这个点前提的前提,
//一定是已经做好了,因为这个点的前提的dp存在,说明这个点的前提也是又前提的前提延生过来的
if((i&fronts[j])!=fronts[j]) continue;
if((i&(1<<(j-1)))) continue;
int tmp=i;
int pay=0;
int flag=0;

for(int k=1;k<=n;k++)
{
if(tmp&(1<<(k-1)))
{
pay+=cost[k];
}
}
if(pay+cost[j]>c||flag) continue;
int now=(i|(1<<(j-1)));
dp[now]=max(dp[now],dp[i]+value[j]);
ans=max(ans,dp[now]);
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU DP ACM