题目: http://codevs.cn/problem/1025/
思路:将价格和钱数浮点型值乘以10后,转换为整型。然后根据数据,将必须菜和美味值为0的菜从所有菜式中剔除。建立一个可选菜式队列,然后使用动态规划算法求解。
题解:
/* 1025 选菜 */
#include <stdio.h>
#define MAXN 101 /* 最大菜式数 */
#define MAXM 1001 /* 最大钱数 */
/* 菜式清单 */
struct _food{
int d; /* 美味值 */
int r; /* 必选标记 */
int p; /* 价格 */
}food[MAXN];
int n, k, m; /* 菜式,必选菜数, 钱数 */
int id[MAXN], delicious[MAXN], prices[MAXN]; /* 价目编号,美味值, 价目表 */
int reqd, required[MAXN]; /* 必选美味值,必选菜单 */
int queue[MAXN], count; /* 可选菜式队列,可选菜计数 */
int maxd[MAXM][MAXN]; /* 最大美味值表 */
/* 01背包算法求解最大美味值表 */
void get_maxd(){
int ic, jr; /* 美味值表行列索引值 */
int f, p; /* 菜式编号,价格 */
/* 初始化第一行 */
f = queue[0];
p = food[f].p;
for(jr = 0; jr <= m; jr++){
/* 菜式价格低于钱数,美味值等于当前菜式美味,否则为0 */
if(p <= jr){
maxd[jr][0] = food[f].d;
}
else{
maxd[jr][0] = 0;
}
}
/* 获取最大美味值表 */
for(ic = 1; ic < count; ic++){
f = queue[ic];
p = food[f].p;
for(jr = 0; jr <= m; jr++){
/* 菜式价格高于总钱数,美味值不变 */
if(p > jr){
maxd[jr][ic] = maxd[jr][ic - 1];
}
/* 否则美味值等于maxd[jr][ic-1] 和maxd[jr-p][ic-1]+food[f].d的最大值 */
else{
if(maxd[jr][ic - 1] > maxd[jr - p][ic - 1] + food[f].d){
maxd[jr][ic] = maxd[jr][ic - 1];
}
else{
maxd[jr][ic] = maxd[jr - p][ic - 1] + food[f].d;
}
}
}
}
/* 测试 - 打印美味值表 */
/*
for(ic = 0; ic < count; ic++){
for(jr = 0; jr <= m; jr++){
printf("%d ", maxd[jr][ic]);
}
printf("\n");
}
*/
}
/* 计算可选菜式队列 */
void queue_food(){
int i, j; /* 索引值 */
int f, d, p; /* 编号,美味,价格 */
int max; /* 最大编号值 */
max = 0;
/* 遍历数据,将菜式保存到结构体中 */
for(i = 1; i <= n; i++){
f = id[i];
food[f].d = delicious[i];
food[f].p = prices[i];
food[f].r = 0;
if(f > max){
max = f;
}
}
/* 遍历必选菜单,更新美味值和钱数 */
reqd = 0;
for(i = 1; i <= k; i++){
f = required[i];
food[f].r = 1;
reqd = reqd + food[f].d;
m = m - food[f].p;
}
/* 遍历菜单,将非必选且美味值不为0的菜式入队 */
count = 0;
for(j = 1; j <= max; j++){
if(0 == food[j].r && food[j].d > 0){
queue[count] = j;
food[j].r = 1;
count++;
}
}
}
/* 主函数入口 */
int main(int argc, char *argv[]) {
int i; /* 索引值 */
float tmp;
/* 打开数据文件 */
FILE *fp;
if(NULL == (fp = fopen("data.txt","r"))){
return 0;
}
/* 获取菜式,必选菜数,钱数 */
fscanf(fp, "%d %d %f", &n, &k, &tmp);
m = tmp * 10;
/* 获取价目表 */
for(i = 1; i <= n; i++){
fscanf(fp, "%f", &tmp);
prices[i] = tmp * 10;
}
/* 获取美味值 */
for(i = 1; i <= n; i++){
fscanf(fp, "%d", &delicious[i]);
}
/* 获取编号 */
for(i = 1; i <= n; i++){
fscanf(fp, "%d", &id[i]);
}
/* 获取必选菜编号 */
for(i = 1; i <= k; i++){
fscanf(fp, "%d", &required[i]);
}
/* 获取菜单队列 */
queue_food();
/* 计算最大美味值表 */
get_maxd();
/* 输出结果 */
printf("%d", reqd + maxd[m][count - 1]);
/* 关闭数据文件 */
fclose(fp);
return 0;
}