算法-订单问题Java实现

在这里插入图片描述
动态规划来实现:

  1. 首先初始化第一行,
    a. 只要能没有达到最大数X,就由A来做
    b. 否则查找之前的A做的最小收益的任务,取当前收益与最小收益的最大值
  2. 接着更新第二行
    a. 凡是A未做的,B一定会做(不然就是题目错了,X+Y一定>=N)。
    b. 若A已做,比较A[i]和B[i]
    (1)若A[i]>B[i],说明A来做更好
    (2)否则,理论上B来做更好,事实上要分情况:
    a. 若B当前已做的数目小于Y(最大数),则B替换A来做
    b. 若B当前已做的数目=Y,计算当前变化量B[i]-A[i],查找之前由B来做的任务且变化量B[j]-A[j]应该比当前变化量更小,这会使得整体收益增大。
    代码如下:
import java.util.Scanner;

public class OrderProblem {
	
	public static int findMinIndex(int[]arr, int n, boolean[]b) {
		int min=Integer.MAX_VALUE,i=-1;
		for(int k=0;k<n;k++) {
			if(b[k] && min>arr[k]) {
				min=arr[k];
				i=k;
			}
		}
		return i;
	}
	
	public static void main(String[]args) {
    	Scanner sc=new Scanner(System.in);
    	int testcase=sc.nextInt();
    	for(int i=0;i<testcase;i++) {
    		int N=sc.nextInt(),X=sc.nextInt(),Y=sc.nextInt();
    		int[]Ai=new int[N+1], Bi=new int[N+1];
    		for(int k=1;k<=N;k++) {
    			Ai[k]=sc.nextInt();
    		}
    		for(int k=1;k<=N;k++) {
    			Bi[k]=sc.nextInt();
    		}
    		int[][]np=new int[2][N+1];
    		boolean[]b=new boolean[N+1];//true-A, false-B
    		//第一行
    		int num=0;
    		for(int k=1;k<=N;k++) {
    			if(num<X) {
    				np[0][k]=np[0][k-1]+Ai[k];
    				num++;
    				b[k]=true;
    			} else {
    				//找到之前最小的一个数,与当前值比较
    				//若当前值更大,则替换,否则不动
    				int index = findMinIndex(Ai, k, b);
    				if(Ai[k]>Ai[index]) {
    					np[0][k]=np[0][k-1]+Ai[k]-Ai[index];
    					b[index]=false;
    					b[k]=true;
    					num++;
    				} 
    			}
    		}
//    		System.out.println(Arrays.toString(np[0]));
    		num=0;
    		//第二行
    		for(int k=1;k<=N;k++) {
    			if(!b[k]) {//A未占用
    				np[1][k]=np[1][k-1]+Bi[k];
    				num++;
    			} else {
    				if(Ai[k]<Bi[k]) {//B来做能有更高的小费
    					if(num<Y) {
    						b[k]=false;
    						np[1][k]=np[1][k-1]+Bi[k];
    						num++;
    					} else {
    						int curSub=Bi[k]-Ai[k];//当前变化量
    						int minSub=curSub,min_j=0;//最小变化量 ,下标
    						for(int j=0;j<k;j++) {
    							//找到B占用,且变化量小于当前变化量的下标(最小变化量)
    							if(!b[j]&&minSub> Bi[j]-Ai[j]) {
    								minSub=Bi[j]-Ai[j];
    								min_j=j;
    							}
    						}
    						if(minSub<curSub) {//将当前的A占用的给B占用,将之前的B占用的min_j给A占用
    							b[k]=false;
        						np[1][k]=np[1][k-1]+Bi[k] - Bi[min_j]+Ai[min_j];
        						num++;
    						} 
    					}
    				} else {
    					np[1][k]=np[1][k-1]+Ai[k];;//A来做能有更高的小费
    				}
    			}
    		}
//    		System.out.println(Arrays.toString(np[1]));
    		System.out.println(np[1][N]);
    	}
      	sc.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学无止境jl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值