感觉这题的难点就是建模;
定义dp[i][j][k]表示数量约束为j,重量约束为k时,前i个矿石的最佳组合对应的最大重量;
数量约束:j<=矿石总数量/2;
重量约束:k<=矿石总重量/2;
第一次写的代码是用三维dp,vivo说空间超过了限制,只通过90%的测试用例。所以又进行降维(去掉第一维),二维dp,代码就可以AC了。
完整代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
/**
* Welcome to vivo
*/
#define MAX_NUM 101
//int solution(int n, int weight[]) {
//
// // TODO Write your code here
// int sum = 0;
// for (int i = 0; i < n; i++)
// sum += weight[i];
// vector<vector<vector<int>>>dp(n + 1, vector<vector<int>>(n / 2 + 1, vector<int>(sum / 2 + 1, 0)));
// for (int i = 1; i <= n; i++)
// for (int j = 1; j <= i&&j <= n / 2; j++)
// for (int k = 0; k <= sum / 2; k++)
// {
// if (weight[i - 1] <= k)
// {
// dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - 1][k - weight[i - 1]] + weight[i - 1]);
// }
// else
// {
// dp[i][j][k] = dp[i - 1][j][k];
// }
// }
// return (sum - dp[n][n / 2][sum / 2]) - dp[n][n / 2][sum / 2];
//}
//降维
int solution(int n, int weight[]) {
// TODO Write your code here
int sum = 0;
for (int i = 0; i < n; i++)
sum += weight[i];
vector<vector<int>>dp(n / 2 + 1, vector<int>(sum / 2 + 1, 0));
for (int i = 1; i <= n; i++)
for (int j = min(i, n / 2); j >= 1; j--)
for (int k = sum / 2; k >= 0; k--)
{
if (weight[i - 1] <= k)
{
dp[j][k] = max(dp[j][k], dp[j - 1][k - weight[i - 1]] + weight[i - 1]);
}
else
{
dp[j][k] = dp[j][k];
}
}
return (sum - dp[n / 2][sum / 2]) - dp[n / 2][sum / 2];
}
int main()
{
string str("");
getline(cin, str);
int a[MAX_NUM];
int i = 0;
char *p;
int count = 0;
const char* strs = str.c_str();
p = strtok((char *)strs, " ");
while (p)
{
a[i] = atoi(p);
count++;
p = strtok(NULL, " ");
i++;
if (i >= MAX_NUM)
break;
}
int result = solution(count, a);
cout << result << endl;
return 0;
}