vcgaoshou 2022-11-01 08:46 采纳率: 100%
浏览 66
已结题

2018年noip提高组初赛题的最后一个填空题

用代码块功能插入代码,请勿粘贴截图
这提是2018年noip提高组初赛题的最后一个填空题。程序的下半段采用动态规划,f记录状态,有几个问题不明白:
1.怎么理解状态转移方程f[j]= min(f[j]+b[i],j>=a[i]? f[j-a[i]]:Inf)中的f[j-a[i]]的含义,为何不是f[j-a[i]]+a[i]
2.有介绍说,这里的f[j],其实是f[i-1][j]的简化,那么当i=0时,f[i-1][j]该如何解释?
完整的代码如下
#include
using namespace std;

const int Inf = 1000;
const int threshold = 410;
const int maxn = 8;

int n=8;
int a[maxn]={30,60,30,40,50,60,70,60};//450*0.95=427.5
int b[maxn]={30,60,60,60,70,80,90,70};
bool put_a[maxn];
int total_a, total_b;

double ans;
double f[threshold];//这个是重点:f[i]表示从当前前缀状态下,买总价格为i的物品,所需要去b商场的最小花费
double min(double x,double y){return x>y?y:x;}
int main(){//16行
int i;
// scanf("%d", &n);
// total_a = total_b = 0; //18行
for (i = 0; i < n; ++i) {
// scanf("%d%d", a + i, b + i);
if (a[i] <= b[i]) total_a += a[i]; //选价格小的,不考虑优惠
else total_b += b[i];
}
ans = total_a + total_b; //不考虑优惠,直接计算总价
total_a = total_b = 0;
for (i = 0; i < n; ++i){
if (a[i] * 0.95 <= b[i]){//买a
put_a[i] = true;
total_a += a[i];
}else{ //买b
put_a[i] = false;
total_b += b[i];
}
}
if (total_a >= threshold){//35行 a商品打折后> threshold,结束
printf("%.2f", total_a * 0.95 + total_b);
return 0;
}
f[0] = 0; //total_a < threshold
for (i = 1; i < threshold; ++i)
f[i] = Inf;
int total_b_prefix = 0;
for (i = 0; i < n; ++i)
if (!put_a[i]) { //如果是b买的,就考虑背包转移
total_b_prefix += b[i]; //当前去b买的物品,所花费的总代价
for (int j = threshold-1; j >= 0; --j) {
if (total_a+j+a[i]>=threshold && f[j]!= Inf)//如果可以转移
ans=min(ans,(total_a+j+a[i])*0.95+f[j]+total_b-total_b_prefix);
//当前去a商场的总花费加上背包体积以及当前物品,乘以折扣,在加上去b商场购买的总价值,是否小于ans
f[j]= min(f[j]+b[i],j>=a[i]? f[j-a[i]]:Inf);//背包转移
//考虑当前的j大小的背包是加上b[i]更优,还是直接靠f[j-a[i]]转移更优(就是考虑当前的背包是加上代价还是状态转移)
}
}
printf("%f", ans);
return 0;
}

  • 写回答

2条回答 默认 最新

  • X-道至简 2022-11-04 10:46
    关注

    我是这样理解的
    第一个问题:怎么理解状态转移方程f[j]= min(f[j]+b[i],j>=a[i]? f[j-a[i]]:Inf)中的f[j-a[i]]的含义,为何不是f[j-a[i]]+a[i]?
    a. 先要弄清楚f[j]和j代表什么含义,f[j]是在total_b_prefix中部分花在b商店的钱, j是total_b_prefix从b商店转移花在a商店的钱,也就是说 f[j] + j = total_b_prefix。希望花在b上的钱更小然后转移到a商店的钱打折后总价更小。
    b. f[j-a[i]]是当前如果j>=a[i],这个时候第i个商品去a店买,也就是转移了a[i]去了a商店,那么剩下的就是去b的店取最小的剩余的钱f[j-a[i]]
    c. 为何不是f[j-a[i]]+a[i] ,这个是f[j]的含义决定的,是花在b商店最小的钱和a没有关系,上面有ans min操作体现了和a的关系
    第二个问题:有介绍说,这里的f[j],其实是f[i-1][j]的简化,那么当i=0时,f[i-1][j]该如何解释?
    这个是应该是降维的操作,简化计算。 然后i=0这种,那个视频里面只是这么介绍便于理解,可以理解i从1开始的,然后把i=0都赋值为inf就行

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 11月16日
  • 已采纳回答 11月8日
  • 创建了问题 11月1日

悬赏问题

  • ¥15 ROS Turtlebot3 多机协同自主探索环境时遇到的多机任务分配问题,explore节点
  • ¥15 Matlab怎么求解含参的二重积分?
  • ¥15 苹果手机突然连不上wifi了?
  • ¥15 cgictest.cgi文件无法访问
  • ¥20 删除和修改功能无法调用
  • ¥15 kafka topic 所有分副本数修改
  • ¥15 小程序中fit格式等运动数据文件怎样实现可视化?(包含心率信息))
  • ¥15 如何利用mmdetection3d中的get_flops.py文件计算fcos3d方法的flops?
  • ¥40 串口调试助手打开串口后,keil5的代码就停止了
  • ¥15 电脑最近经常蓝屏,求大家看看哪的问题