题目链接:1534 - Taekwondo
题意:两组人比赛,一组n1人,一组n2人,选择min(n1,n2)组出来,要求两两人重量差绝对值之和最小。
思路:首先先预处理让n1变成人少的一组,人少的每个人都必须去匹配,dp[i][j] i表示n1组第i个人,j表示第二组多少人没匹配,于是匹配的时候n1组的第i人就和n2组的第i + j的人去匹配,然后进行状态转移
dp[i][j] = {dp[i - 1][k] + fabs(a1[i] - a2[i + j]), (0 <= k <= abs(n1 - n2)},这样时间复杂度要O(n^3),进行优化,dp[i - 1][k]可以在第二城循环的时候顺便维护一个最小值Min,这样复杂度优化到O(n^2)。
代码:
#include <stdio.h> #include <string.h> #include <algorithm> #include <stdlib.h> #include <math.h> using namespace std; #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define INF 0x3f3f3f3f const int N = 505; int t, n1, n2, i, j, k; double a1[N], a2[N], dp[N][N]; void tra() { if (n1 > n2) { for (int i = 1; i <= n1; i++) { double t = a1[i]; a1[i] = a2[i]; a2[i] = t; } int t = n1; n1 = n2; n2 = t; } k = n2 - n1; } int main() { scanf("%d", &t); while (t--) { double ans = INF; scanf("%d%d", &n1, &n2); for (i = 1; i <= n1; i++) scanf("%lf", &a1[i]); for (i = 1; i <= n2; i++) scanf("%lf", &a2[i]); tra(); sort(a1 + 1, a1 + n1 + 1); sort(a2 + 1, a2 + n2 + 1); for (i = 1; i <= n1; i++) { double Min = INF; for (j = 0; j <= k; j++) { if (i + j > n2) break; Min = min(Min, dp[i - 1][j]); dp[i][j] = INF; dp[i][j] = min(dp[i][j], Min + fabs(a1[i] - a2[i + j])); if (i == n1) ans = min(ans, dp[i][j]); } } printf("%.1lf\n", ans); } return 0; }
UVA 1534 - Taekwondo(dp),码迷,mamicode.com
时间: 2024-10-05 22:27:01