1 条题解
-
0
#include<bits/stdc++.h> using namespace std; int t,n,k; // [1] t-测试用例数量;n-地点总数;k-餐馆之间的最小距离限制 int arr[200]; // [2] arr数组-存储每个地点的位置(输入时已按升序排列) int brr[200]; // [3] brr数组-存储每个地点开餐馆的利润 int dp[200]; // [4] dp数组-动态规划数组,dp[i]表示前i个地点中选择,能获得的最大利润 int main(){ cin>>t; // [5] 读取测试用例的数量 while(t--){ // [6] 循环处理每个测试用例 cin>>n>>k; // [7] 读取当前测试用例的地点数n和距离限制k for(int i=1;i<=n;i++) cin>>arr[i]; // [8] 读取每个地点的位置,存入arr数组(下标从1开始对应第1到第n个地点) for(int i=1;i<=n;i++) cin>>brr[i]; // [9] 读取每个地点的利润,存入brr数组 /* 问题分析:选择地点开餐馆,要求餐馆间距离>k,目标是总利润最大。 每个地点有两种状态:开或不开。动态规划的核心是状态转移。 */ memset(dp,0,sizeof(dp)); // [10] 初始化dp数组为0,每个测试用例独立计算 for(int i=1;i<=n;i++){ // (1) 第i个地点不开店:当前最大利润等于前i-1个地点的最大利润 dp[i]=dp[i-1]; // (2) 第i个地点开店:需要找到最后一个满足「与i的距离>k」的地点v,这样v之前的选择可以和i同时存在 // 因为arr数组是有序的,用二分查找高效定位v int l=1,r=i-1,v=0; // [11] l/r-二分查找的左右边界;v-记录满足条件的最远地点,初始为0(表示无符合条件的地点) while(l<=r){ int mid=(l+r)/2; // [12] 计算二分中间位置 if(arr[i]-arr[mid]<=k){ // 距离不满足要求(<=k),需要向左寻找更远的地点 r=mid-1; }else{ // 距离满足要求(>k),记录当前mid为候选v,并向右寻找更远的可能地点 v=mid; l=mid+1; } } // 计算开店的利润并更新dp[i] if(v==0){ // 没有找到符合条件的地点,说明只能单独开当前店,利润为brr[i] dp[i] = max(dp[i], brr[i]); }else{ // 可以和前v个地点的最优选择组合,利润为dp[v] + brr[i] dp[i]=max(dp[i],dp[v]+brr[i]); } } cout<<dp[n]<<endl; // [13] 输出当前测试用例的最大利润(前n个地点的最优解) } return 0; }
- 1
信息
- ID
- 1324
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者