ByteDance 2019 校招题目及答案

 Question 3

// 也看到了其他解答,但是都只是考虑到一定有答案的测试用例,或者代码有bug,所以才写出这个答案

小a和小b玩一个游戏,有n张卡牌,每张上面有两个正整数x,y。取一张牌时,个人积分增加x,团队积分增加y。求小a,小b各取若干张牌,使得他们的个人积分相等,且团队积分最大。

输入描述:
    第一行n
    接下来n行,每行两个正整数x,y
输出描述:
    一行一个整数
    表示小a的积分和小b的积分相等时,团队积分的最大值
例:输入
        4
        3 1
        2 2
        1 4
        1 4
    输出:10
说明:当a抽取(2,2),b抽取(1,4),(1,4)时,两人个人积分都是2,团队积分最大,为10分

解析:可以使用动态规划解决

设:

    有n张扑克牌,扑克牌上的个人积分存储为vx,团队积分存储为vy,个人积分的和为sumx

    vp[i,j]为选择到第i张扑克牌,个人积分差值为j时的团队积分,有:

状态转移公式:

 vp[i][j] = max \left\{\begin{matrix} vp[i-1][j] & , A\ and\ B\ didn't\ get\ the\ i-th\ card \\ vp[i-1][j - vx[i]] + vy[i] & , A\ get\ the\ i\_{}th\ card \\ vp[i-1][j + vx[i]] + vy[i] & , B\ get\ the\ i\_{}th\ card \end{matrix}\right.

注:vx和vy根据vy降序排序。特别注意在公式中的vp[i-1][j-vx[i]] 和 vp[i-1][j+vx[i]] 可能不存在有效值,还有就是在i=0时有一些选择是禁忌项(不可达选项, 所有不可达的项设置为-1) , vp为n * (sumx + 1) 的二维数组。

有初始化值:

vp[0][j] = \left\{\begin{matrix} vy[0] & , j = vx[0] \\ -1 & , else \end{matrix}\right.

// 状态转移公式中的值也要讨论,展开比较复杂(写公式麻烦),代码中有体现。

Java实现 :

import java.util.Scanner;

public class SelectCard2 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] vx = new int[n];
		int[] vy = new int[n];
		int sumx = 0;
		for (int i = 0; i < n; i++) {
			vx[i] = in.nextInt();
			vy[i] = in.nextInt();
			sumx += vx[i];
		}
		in.close();
		sort(vx, vy);
		int[][] vp = new int[n][sumx + 1];

		for (int i = 0; i < sumx + 1; i++) {
			vp[0][i] = -1;
		}
		vp[0][0] = 0;  //
		vp[0][vx[0]] = vy[0];

		for (int i = 1; i < n; i++) {
			for (int j = 0; j < sumx + 1; j++) {
				int Non = vp[i - 1][j];
				int BHave = j - vx[i] < 0 || vp[i - 1][j - vx[i]] < 0 ? -1 : vp[i - 1][j - vx[i]] + vy[i];
				int AHave = j + vx[i] >= sumx + 1 || vp[i - 1][j + vx[i]] < 0 ? -1 : vp[i - 1][j + vx[i]] + vy[i];

				int tmp = Non > BHave ? Non : BHave;
				vp[i][j] = tmp > AHave ? tmp : AHave;
			}
		}
		System.out.println(vp[n - 1][0]);
		
	}

	public static void sort(int[] vx, int[] vy) {
		int rows = vx.length;
		for (int i = 0; i < rows; i++) {
			for (int j = i + 1; j < rows; j++) {
				if (vy[i] < vy[j]) {
					swap(vy, i, j);
					swap(vx, i, j);
				}
			}
		}
	}

	public static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

 

测试用例

1.  //题目提供的测试用例

2. 

输入:
4
1 4
1 4
2 2
3 15
输出:
21

 3. 无解测试用例

输入:
2
1 3
2 4
输出:
0

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值