The chef of a restaurant aspiring for a Michelin star wants to display a selection of her signature dishes for inspectors. For this, she has allocated a maximum budget B for the cumulated cost, and she wants to maximize the cumulated prestige of the dishes that she is showing to the inspectors.
To measure the prestige of her dishes, the chef maintains a list of recipes, along with their costs and ingredients. For each recipe, a derived dish is obtained from a base dish by adding an ingredient. The recipe mentions two extra pieces of information: the cost of applying the recipe, on top of the cost of the base dish, and the prestige the recipe adds to the prestige of the base dish. The chef measures the prestige by her own units, called “prestige units.”
For example, a recipe list for making pizza looks like:
• pizza_tomato pizza_base tomato 1 2
• pizza_classic pizza_tomato cheese 5 5
Here, pizza_base is an elementary dish, a dish with no associated recipe, a dish so simple that its cost is negligible (set to 0) and its prestige also 0. The chef can obtain the derived dish pizza_tomato by adding the ingredient tomato to the base dish pizza_base, for a cost of 1 euro and a gain of 2 prestige units. A pizza_classic is obtained from a pizza_tomato by adding cheese, for an added cost of 5, and a prestige of 5 added to the prestige of the base dish; this means the total cost of pizza_classic is 6 and its total prestige is 7.
A signature dish selection could for instance include both a pizza_tomato and a pizza_classic. Such a selection would have cumulated total prestige of 9, and cumulated total cost of 7.
Armed with the list of recipes and a budget B, the chef wants to provide a signature dish selection to Michelin inspectors so that the cumulated total prestige of the dishes is maximized, keeping their cumulated total cost at most B.
Important Notes
• No dish can appear twice in the signature dish selection.
• Any dish that does not appear as a derived dish in any recipe is considered to be an elementary
dish, with cost 0 and prestige 0.
• A dish can appear more than once as a resulting dish in the recipe list; if there is more than one
way to obtain a dish, the one yielding the smallest total cost is always chosen; if the total costs
are equal, the one yielding the highest total prestige should be chosen.
• The recipes are such that no dish D can be obtained by adding one or more ingredients to D
itself.
Input
• The first line consists of the budget B, an integer.
• The second line consists of the number N of recipes, an integer.
• Each of the following N lines describes a recipe, as the following elements separated by single
spaces: the derived dish name (a string); the base dish name (a string); the added ingredient (a string); the added price (an integer); the added prestige (an integer).
10
Limits
• 0��<=B<=��10000;
• 0<=��N<=��1000000;
• there can be at most 10 000 different dishes (elementary or derived);
• costs and prestiges in recipes are between 1 and 10 000 (inclusive);
• strings contain at most 20 ASCII characters (letters, digits, and ’_’ only).
Output
The output should consist of two lines, each with a single integer. On the first line: the maximal cumulated prestige within the budget. On the second line: the minimal cumulated cost corresponding to the maximal cumulated prestige, necessarily less than or equal to the budget.
Sample Input
15
6
pizza_tomato pizza_base tomato 1 2
pizza_cheese pizza_base cheese 5 10
pizza_classic pizza_tomato cheese 5 5
pizza_classic pizza_cheese tomato 1 2
pizza_salami pizza_classic salami 7 6
pizza_spicy pizza_tomato chili 3 1
Sample Output
25
15
1
2
题意:
给出最大成本B,n个菜谱,每条菜谱代表一种成品:原料(其他菜谱做出来的)+辅料(不花钱,无声望),需要消耗a的代价产生b的声望。要求用最小的成本产生最大的声望。
样例解释:
pizza_tomato pizza_base tomato 1 2
pizza_cheese pizza_base cheese 5 10
pizza_classic pizza_tomato cheese 5 5
pizza_classic pizza_cheese tomato 1 2
pizza_salami pizza_classic salami 7 6
pizza_spicy pizza_tomato chili 3 1
pizza_tomato: 1 2
pizza_cheese:5 10
pizza_classic:pizza_tomato+本身=6 7(依据题意去掉)
pizza_classic:pizza_cheese+本身=6 12
pizza_salami:13 18
pizza_spicy: 4 3
选:pizza_cheese+pizza_classic+pizza_spicy
思路:
如果我们知道每种成品的代价和声望的话很明显这就是一个01背包的题,但是我们知道每一种产品都是有一种原料制作而成,所以说我们需要把原料加进入(pizza_base+辅料(tomato。。。。。)),然后根据这个推出他可以制作出来的成品,成品又可以往外推。。。。。。。一个拓扑排序的即可,只不过不是出度入读,而是根据制作该产品的顺序(红字的描述)
具体流程:s1 s2 s3 a b
首先将三个字符串在map当中映射id1,id2,id3,把id2 id3当作无向边建图<id2,id3,i(id1)>,表示id2和id3可以造出id1这个成品,用行号i表示(这样如果有两个方案可以造同一件物品,那他也不会被遗漏,用vis[i]表示行号为i是否被制造过),ind表示被造成品的方案数量,我们知道上述物品如果为辅料或者pizza_base,一定ind=0,会被首先加入队列,根据他们造出一批次的物品,对应的ind--,直到ind减少完才能进入下一批次的建造。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
const int inf=0x3f3f3f3f;
int B, n;
char s1[N][24];
char s2[N][24];
char s3[N][24];
int c[N];
int v[N];
int cc[N];
int vv[N];
int ind[N];
int sta[N];
map<string, int>mop;
int ID;
vector< pair<int,int> >a[N];
int getid(char s[24])
{
if(!mop.count(s))
{
mop[s] = ++ID;
a[ID].clear();
cc[ID] = inf;
vv[ID] = -inf;
ind[ID] = 0;
}
return mop[s];
}
int vis[N];
LL f[10005];
void topo()
{
queue<int> q;
for(int i = 1; i <= ID; ++i)
if(ind[i] == 0)
{
q.push(i);
cc[i] = vv[i] = 0;
}
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=0;i<a[x].size();i++)
{
pair<int,int> it=a[x][i];
int y = it.first;
int id = it.second;
if(vis[id]==0 && ind[y] == 0)
{
vis[id] = 1;
int z = mop[s1[id]];
int cost = cc[x] + cc[y] + c[id];
int val = vv[x] + vv[y] + v[id];
if(cost < cc[z] || cost == cc[z] && val > vv[z])
{
cc[z] = cost;
vv[z] = val;
}
if(--ind[z] == 0)
{
q.push(z);
}
}
}
}
}
int main()
{
while(~scanf("%d%d", &B, &n))
{
ID = 0;
mop.clear();
for(int i = 1; i <= n; ++i)
{
scanf("%s%s%s%d%d", s1[i], s2[i], s3[i], &c[i], &v[i]);
int z = getid(s1[i]);
int x = getid(s2[i]);
int y = getid(s3[i]);
++ind[z];
a[x].push_back({y, i});
a[y].push_back({x, i});
vis[i] = 0;
}
topo();
/*for(int i=1;i<=ID;i++)
{
cout<<cc[i]<<" "<<vv[i]<<endl;
} */
memset(f,-127,sizeof(f));
f[0] = 0;
for(int i = 1; i <= ID; ++i)
{
for(int j = B; j >= cc[i]; --j)
{
f[j]=max(f[j],f[j - cc[i]] + vv[i]);
}
}
int cost = 0;
LL val = 0;
for(int i = 1; i <= B; ++i)
{
if(f[i] > val)
{
val = f[i];
cost = i;
}
}
printf("%lld\n%d\n", val, cost);
}
return 0;
}