把距离从小到大排序
d[i][j]表示有前i个男生和前j个女生的最优方案
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<deque>
#include<iostream>
#include<map>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
const int MAXN = 2011;
const int MAXM = 2011 * 3;
int n, m;
struct Node {
char A[20];
int x;
bool operator < (const Node &t) const {
return x < t.x;
}
} boy[MAXN+10], girl[MAXM+10];
int d[MAXN+10][MAXM+10], Boy[MAXN+10][MAXM+10], Girl[MAXN+10][MAXM+10];
char Name[4][20];
void dp()
{
memset(d, 0x3f, sizeof(d));
d[0][0] = 0;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= m; j++)
{
int dis = boy[i].x;
for(int k = 0; k <= ((3 < j) ? 3 : j); k++) {
if(d[i-1][j-k] + dis < d[i][j]) {
d[i][j] = d[i-1][j-k] + dis;
Boy[i][j] = 1; Girl[i][j] = k;
}
dis = max(dis, girl[j-k].x);
}
dis = boy[i].x;
if(i > 1) {
for(int k = 0; k <= ((2 < j) ? 2 : j); k++) {
if(d[i-2][j-k] + dis < d[i][j]) {
d[i][j] = d[i-2][j-k] + dis;
Boy[i][j] = 2; Girl[i][j] = k;
}
dis = max(dis, girl[j-k].x);
}
}
dis = boy[i].x;
if(i > 2) {
for(int k = 0; k <= ((1 < j) ? 1 : j); k++) {
if(d[i-3][j-k] + dis < d[i][j]) {
d[i][j] = d[i-3][j-k] + dis;
Boy[i][j] = 3; Girl[i][j] = k;
}
dis = max(dis, girl[j-k].x);
}
}
dis = boy[i].x;
if(i > 3)
if(d[i-4][j] + dis < d[i][j]) {
d[i][j] = d[i-4][j] + dis;
Boy[i][j] = 4; Girl[i][j] = 0;
}
}
}
}
int main()
{
freopen("taxi.in", "r", stdin);
SF("%d", &n);
for(int i = 1; i <= n; i++) cin >> boy[i].A >> boy[i].x;
SF("%d", &m);
for(int i = 1; i <= m; i++) cin >> girl[i].A >> girl[i].x;
sort(boy+1, boy+1+n); sort(girl+1, girl+1+m);
dp();
PF("%d\n", d[n][m]);
PF("%d\n", (n + m + 3) / 4);
int cnt = 0;
int i = n, j = m;
while(i) {
PF("Taxi %d: ", ++cnt);
int tot = 0;
int t1 = i - Boy[i][j] + 1, t2 = j - Girl[i][j] + 1;
for( ; i >= t1; i--) strcpy(Name[tot++], boy[i].A);
for( ; j >= t2; j--) strcpy(Name[tot++], girl[j].A);
if(tot == 1) PF("%s.\n", Name[0]);
if(tot == 2) PF("%s and %s.\n", Name[0], Name[1]);
if(tot == 3) PF("%s, %s and %s.\n", Name[0], Name[1], Name[2]);
if(tot == 4) PF("%s, %s, %s and %s.\n", Name[0], Name[1], Name[2], Name[3]);
}
}