【题目大意】
一个足球队有4种位置,门将、前锋、中锋、后卫,每种位置的总人数确定。从n个人中选11个人组成足球队,要使得队伍的总评分最高。总评分计算方式如下:总评分分为两部分,sum_ca,sum_pa。如果一个人确定了位置,总评分将会加上对应的ca,pa。特别的,所有人有喜欢、不喜欢的关系,如果队内的两人喜欢,那么sum_ca将加上一个w,如果不喜欢,则减去w。总评分大小判断关系:可将sum_ca,sum_pa视为一个pair,前者优先级高。
【思路】
这个居然是DP......这个居然是DP......这个居然是DP......这个DP居然还不是很难......
首先枚举具体选的11个人,把额外的加分算出来。dp[ i ][ j ][ k ][ k1 ]表示前i个人已经确定了位置,门将有j人,前锋有k人,中锋有k1人,最高的评分。然后推一下就好了。因为时间很紧,需要加上最优化剪枝。另外,我们可以通过交换,使得dp没有开的那一维最可能的大,这样的极限状态只有11*2*4*4 == 352。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100111222;
const double INFF=1e200;
const double eps=1e-8;
const int mod=1000000007;
const int NN=505;
const int MM=100010;
/* ****************** */
struct node
{
bool fg[4];
int ca[4],pa[4];
void init()
{
memset(fg,false,sizeof(fg));
}
}a[25];
int id_to[105];
int val[25][25];
int num[4];
bool fg;
int ans_ca,ans_pa;
int re[25];
pair<int,int> dp[12][3][5][5];
void goo()
{
int ex=0,jian=0;
int i,j,t,k,k1,t1,t2;
int max_num[4];
pair<int,int> temp;
for(i=1;i<=11;i++)
for(j=1;j<=11;j++)
{
ex += val[ re[i] ][ re[j] ];
}
memset(max_num,0,sizeof(max_num));
for(i=1;i<=11;i++)
{
t=0;
for(j=0;j<4;j++)
if( a[ re[i] ].fg[j] )
{
t = max(t,a[re[i]].ca[j]);
max_num[j]++;
}
jian+=t;
}
for(j=0;j<4;j++)
{
if(max_num[j]<num[j])
return;
}
if(fg && ex+jian<ans_ca)
return;
for(i=0;i<=11;i++)
for(j=0;j<=1;j++)
for(k=0;k<=num[1];k++)
for(k1=0;k1<=num[2];k1++)
dp[i][j][k][k1] = MP(-INF,-INF);
dp[0][0][0][0] = MP(0,0);
for(i=0;i<11;i++)
for(j=0;j<=1;j++)
for(k=0;k<=num[1];k++)
for(k1=0;k1<=num[2];k1++)
if(dp[i][j][k][k1].first!=-INF)
{
t1 = dp[i][j][k][k1].first;
t2 = dp[i][j][k][k1].second;
if(a[re[i+1]].fg[0])
{
temp = MP(t1+a[re[i+1]].ca[0],t2+a[re[i+1]].pa[0]);
dp[i+1][j+1][k][k1]=max(dp[i+1][j+1][k][k1],temp);
}
if(a[re[i+1]].fg[1])
{
temp = MP(t1+a[re[i+1]].ca[1],t2+a[re[i+1]].pa[1]);
dp[i+1][j][k+1][k1]=max(dp[i+1][j][k+1][k1],temp);
}
if(a[re[i+1]].fg[2])
{
temp = MP(t1+a[re[i+1]].ca[2],t2+a[re[i+1]].pa[2]);
dp[i+1][j][k][k1+1]=max(dp[i+1][j][k][k1+1],temp);
}
if(a[re[i+1]].fg[3])
{
temp = MP(t1+a[re[i+1]].ca[3],t2+a[re[i+1]].pa[3]);
dp[i+1][j][k][k1]=max(dp[i+1][j][k][k1],temp);
}
}
temp = dp[11][1][num[1]][num[2]];
if(temp.first>-INF)
{
int cca = temp.first + ex;
int ppa = temp.second;
if(fg)
{
if(cca>ans_ca)
{
ans_ca = cca;
ans_pa = ppa;
}
else if(cca == ans_ca)
ans_pa = max(ans_pa,ppa);
}
else
{
fg=true;
ans_ca = cca;
ans_pa = ppa;
}
}
}
void dfs(int now,int deep,int ge)
{
if(ge==11)
{
goo();
return;
}
if(now==deep+1)
return;
//xuan
re[ge+1]=now;
dfs(now+1,deep,ge+1);
//bu xuan
if(ge+deep-now>=11)
dfs(now+1,deep,ge);
}
void solve(int n)
{
fg=false;
dfs(1,n,0);
if(fg)
{
printf("%d %d\n",ans_ca,ans_pa);
}
else
{
puts("Poor Manager!");
}
}
int main()
{
char op[50];
int cas;
int n,m,ge,ca,pa,id;
int wei,i,j,w,u,v,t;
scanf("%d",&cas);
while(cas--)
{
scanf("%d",&n);
memset(id_to,0,sizeof(id_to));
for(i=1;i<=n;i++)
{
scanf("%d",&t);
id_to[t] = i;
scanf("%d",&ge);
a[i].init();
for(j=0;j<ge;j++)
{
scanf("%s%d%d",op,&ca,&pa);
if(strcmp(op,"GK")==0)
wei = 0;
else if(strcmp(op,"DF")==0)
wei = 1;
else if(strcmp(op,"MF")==0)
wei = 2;
else
wei = 3;
if(a[i].fg[wei])
{
if(ca>a[i].ca[wei])
{
a[i].ca[wei] = ca;
a[i].pa[wei] = pa;
}
else if(ca==a[i].ca[wei])
a[i].pa[wei] = max(a[i].pa[wei], pa);
}
else
{
a[i].fg[wei] = true;
a[i].ca[wei] = ca;
a[i].pa[wei] = pa;
}
}
}
memset(val,0,sizeof(val));
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d%d%s%d",&u,&v,op,&w);
u = id_to[u];
v = id_to[v];
if(op[0]=='D')
{
val[v][u]-=w;
}
else
{
val[v][u]+=w;
}
}
num[0]=1;
scanf("%d-%d-%d",&num[1],&num[2],&num[3]);
id=3;
if(num[1]>num[2] && num[1]>num[3])
id=1;
if(num[2]>num[1] && num[2]>num[3])
id=2;
swap(num[id],num[3]);
for(i=1;i<=n;i++)
{
swap(a[i].fg[id],a[i].fg[3]);
swap(a[i].ca[id],a[i].ca[3]);
swap(a[i].pa[id],a[i].pa[3]);
}
solve(n);
}
return 0;
}