1 条题解

  • 0
    @ 2026-1-27 18:53:42
    #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
    上传者