小团是美团汽车租赁公司的调度师,某个时刻A和B两地都向该公司提交了租车的订单,分别需要a和b辆汽车。此时,公司的所有车辆都在外运营,通过北斗定位,可以得到所有车辆的位置,小团分别计算了每辆车前往A地和B地完成订单的利润。作为一名精明的调度师,当然是想让公司的利润最大化了。
请你帮他分别选择a辆车完成A地的任务,选择b辆车完成B地的任务。使得公司获利最大,每辆车最多只能完成一地的任务。
小团是美团汽车租赁公司的调度师,某个时刻A和B两地都向该公司提交了租车的订单,分别需要a和b辆汽车。此时,公司的所有车辆都在外运营,通过北斗定位,可以得到所有车辆的位置,小团分别计算了每辆车前往A地和B地完成订单的利润。作为一名精明的调度师,当然是想让公司的利润最大化了。
请你帮他分别选择a辆车完成A地的任务,选择b辆车完成B地的任务。使得公司获利最大,每辆车最多只能完成一地的任务。
输入第一行包含三个整数n,a,b,分别表示公司的车辆数量和A,B两地订单所需数量,保证a+b<=n。(1<=n<=2000)
接下来有n行,每行两个正整数x,y,分别表示该车完成A地任务的利润和B地任务的利润。
输出仅包含一个正整数,表示公司最大获得的利润和。
5 2 2 4 2 3 3 5 4 5 3 1 5
18
#include<iostream> #include<cstring> using namespace std; int main( ) { int n,a,b; cin>>n>>a>>b; int tab[a+1][b+1]; memset(tab,0,sizeof(tab)); int fx,fy; for(int i=1;i<=n;i++){ cin>>fx>>fy; for(int j=min(a, i);j>= 0;j--){//j>=Math.max(0, a - n + i) a+b<n , 剩余的车要有单接 max(0, a - n + i) for(int k= min(b, i-j);k>= 0;k--){//max(0, a +b - n + i-j) int r1=tab[j][k]; if(j>=1){ int r2=tab[j-1][k]+fx ; if(r2>r1)r1=r2; } if(k>=1){ int r3=tab[j][k-1]+fy ; if(r3>r1)r1=r3; } tab[j][k]=r1; } } } cout<<tab[a][b] ; }
#include<bits/stdc++.h> using namespace std; int n,a,b; int main(){ scanf("%d%d%d",&n,&a,&b); int dp[a+1][b+1]; memset(dp, 0, sizeof(dp)); int x,y; for(int k=1;k<=n;k++){ scanf("%d%d",&x,&y); for(int i=min(a,k);i>=0;i--){ for(int j=min(b,k-i);j>=0;j--){ //使用max()比较的话会超时 if(j>0&&dp[i][j]<dp[i][j-1]+y) dp[i][j]=dp[i][j-1]+y; if(i>0&&dp[i][j]<dp[i-1][j]+x) dp[i][j]=dp[i-1][j]+x; } } } printf("%d\n",dp[a][b]); }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main{ public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().trim().split(" "); int n = Integer.parseInt(params[0]); int a = Integer.parseInt(params[1]); int b = Integer.parseInt(params[2]); int x, y; // 循环到i时,dp[j][k]表示前i辆车中派出j辆到A地,派出k辆到B地可以获得的最大利润 int[][] dp = new int[a + 1][b + 1]; for(int i = 1; i <= n; i++) { params = br.readLine().trim().split(" "); x = Integer.parseInt(params[0]); y = Integer.parseInt(params[1]); for(int j = Math.min(a, i); j >= 0; j--) { for(int k = Math.min(b, i - j); k >= 0; k--) { if(j == 0 && k == 0) continue; if(k == 0){ // B地的车够了,第i辆车不派出或者派到A地 dp[j][k] = Math.max(dp[j][k], dp[j - 1][k] + x); }else if (j == 0){ // A地的车够了,第i辆车不派出或者派到B地 dp[j][k] = Math.max(dp[j][k], dp[j][k - 1] + y); }else{ // 此时第i辆车可以选择往A地派也可以选择往B地派或不派 dp[j][k] = Math.max(dp[j][k], Math.max(dp[j - 1][k] + x, dp[j][k - 1] + y)); } } } } System.out.println(dp[a][b]); } }第二层循环的起点表示:如果 i 小于a,是不可能派出a辆车的,如果 i 大于a,也不可能派出超过a辆车去A地,相当于剪枝。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main{ public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().trim().split(" "); int n = Integer.parseInt(params[0]); int a = Integer.parseInt(params[1]); int b = Integer.parseInt(params[2]); int x, y; // 循环到i时,dp[j][k]表示前i辆车中派出j辆到A地,派出k辆到B地可以获得的最大利润 int[][] dp = new int[a + 1][b + 1]; for(int i = 1; i <= n; i++) { params = br.readLine().trim().split(" "); x = Integer.parseInt(params[0]); y = Integer.parseInt(params[1]); for(int j = Math.min(a, i); j >= Math.max(0, a - n + i); j--) { for(int k = Math.min(b, i - j); k >= Math.max(0, a + b - n + i - j); k--) { if(j == 0 && k == 0) continue; if(k == 0){ // B地的车够了,第i辆车不派出或者派到A地 dp[j][k] = Math.max(dp[j][k], dp[j - 1][k] + x); }else if (j == 0){ // A地的车够了,第i辆车不派出或者派到B地 dp[j][k] = Math.max(dp[j][k], dp[j][k - 1] + y); }else{ // 此时第i辆车可以选择往A地派也可以选择往B地派或不派 dp[j][k] = Math.max(dp[j][k], Math.max(dp[j - 1][k] + x, dp[j][k - 1] + y)); } } } } System.out.println(dp[a][b]); } }
python 优化后还是被卡了时间。可以顺便看看 97. 交错字符串 - 力扣(LeetCode) ,这两道题很像。
n, a, b = list(map(int, input().split(" "))) profit_a, profit_b = [0], [0] for _ in range(n): x, y = list(map(int, input().split(" "))) profit_a.append(x), profit_b.append(y) pre = [[0] * (b + 1) for _ in range(a + 1)] cur = [[0] * (b + 1) for _ in range(a + 1)] for i in range(1, n + 1): for j in range(a + 1): for k in range(b + 1): if j + k > i: break if j == 0 and k == 0: continue if k == 0: cur[j][k] = max(pre[j][k], pre[j - 1][k] + profit_a[i]) elif j == 0: cur[j][k] = max(pre[j][k], pre[j][k - 1] + profit_b[i]) else: p_a = pre[j - 1][k] + profit_a[i] p_b = pre[j][k - 1] + profit_b[i] cur[j][k] = max(pre[j][k], p_a, p_b) pre, cur = cur, pre print(pre[a][b])
#include "bits/stdc++.h" using namespace std; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, a, b; std::cin >> n >> a >> b; // 选a个first, b个second -> max profit // 前i辆车,j个first,k个second std::vector<std::vector<std::vector<int>>> dp(2, std::vector<std::vector<int>>(a + 1, std::vector<int>(b + 1))); for (int i = 1;i <= n; i++) { int now = i & 1, pre = now ^ 1; int x, y; std::cin >> x >> y; for(int j = min(i, a);j >= max(0, a - (n - i)); j--) { for(int k = min(b, i - j);k >= max(0, a + b - n + i - j); k--) { dp[now][j][k] = dp[pre][j][k]; if(j) dp[now][j][k] = max(dp[now][j][k], dp[pre][j - 1][k] + x); if(k) dp[now][j][k] = max(dp[now][j][k], dp[pre][j][k - 1] + y); } } } std::cout << dp[n & 1][a][b] << std::endl; }