【题目描述】
The Farmer’s Canteen的点菜方式如同在超市自选商品一样,人们从一个指定的路口进去,再从一个指定的路口出来并付款。由于来这里就餐的人数比较多,所以人们自觉地在进入口的时候就排成一个长队,沿着长长的摆放着各式各样佳肴的桌子进行选菜。
小松发现,这种选菜方式意味着,他不能在选菜的时候离开队伍去拿一些他已经看过了的菜或者没有看过的菜。
每个菜有一个价值,而小松也自己给每个菜定了一个在他看来的美味价值,而有一些菜是营养价值极其高的菜,所以无论它的美味价值是多少,小松都会选择1份。现在小松带了X元钱来食堂就餐,他想知道,在不欠帐的情况下,他选菜的美味价值总合最大是多少。
输入的第一行包括两个整数n(1 ≤ n ≤ 100)、k(0 ≤ k ≤ 实际菜的种类)和一个实数X(0 ≤ X ≤ 100),表示有n个菜式,有k种菜是必选的,小松带来了X元钱(精确到“角”);
接下来的1行包含n个实数,表示菜桌上从入口到出口的所有菜的价格(0 ≤ 价格 ≤ 10,单位“元”,精确到“角”);
再接下来的1行包含n个整数,表示菜桌上从入口到出口的所有菜的美味价值(0 ≤ 美味价值 ≤ 100);
再接下来一行包含n个整数,表示菜桌上从入口到出口的所有菜的种类编号(1 ≤ 种类编号 ≤ 100);
最后一行包含k个整数,分别表示必选菜的种类编号。要注意的是,同一种编号的菜可以出现多次,但是他们的价格和美味价值都是一样的。对于同一种菜,小松最多只会选择1份。另外,必选菜的价格之和一定不超过X。
输出包含一个整数,表示小松能选到的菜的美味价值总和最大是多少。
数据中不会出现小松带的钱不够买必买菜的情况。
7 1 5.0
4 1 3 0.9 2 0.5 0.9
7 3 5 2 5 0 2
6 3 5 2 4 1 2
2
10
源代码: #include<cstdio> int n,k,v,num(0),i1[101],i[101],h1[101],h[101],f[100001]={0}; int main() { float t; scanf("%d%d%f",&n,&k,&t); v=t*10; //巧妙的方法。 for (int a=1;a<=n;a++) { float t; scanf("%f",&t); h1[a]=t*10; } for (int a=1;a<=n;a++) scanf("%d",&i1[a]); for (int a=1;a<=n;a++) { int t; scanf("%d",&t); i[t]=i1[a]; h[t]=h1[a]; } //去重。 for (int a=1;a<=k;a++) { int t; scanf("%d",&t); num+=i[t]; v-=h[t]; i[t]=0; h[t]=0; } //预处理必选菜。 for (int a=1;a<=n;a++) for (int b=v;b>=h[a];b--) f[b]=f[b]>f[b-h[a]]+i[a]?f[b]:f[b-h[a]]+i[a]; printf("%d",f[v]+num); //不要忘了相加。 return 0; }