##uva1379这个题目主要是考察在进行状态转移过程中如何节省时间和空间的开销,在这个题目里面运用了滚动数组,使得空间节省,利用贪心节省时间和空间,在求解之前,要分析在这个dp中的状态转移,dp【date】【i】【j】【k】【l】分别表示第date天,前四天分别对应的队伍,,,在进行状态转移贪心主要运用在其休息4天方可再进行比赛,,那么我们只需要取前五名的即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define maxn 1000
#define rep(i,n) for(int i=0;i<n;i++)
struct node {
int x;
int id;
}a[110][105];
int dp[2][6][6][6][6];
int d[300];
bool cmp(node x,node y)
{
return x.x>y.x;
}
int n,m,g;
void solve()
{
memset(dp,0,sizeof(dp));
int cnt=0;
for(int i=g;i>=1;i--)
{
memset(dp[cnt],0,sizeof(dp[cnt]));
rep(j,6)
rep(k,6)
rep(l,6)
rep(r,6){
int p=d[i];
if(p)
{
int s;
for(s=1;s<=5;s++)//只需要到达第五大即可,,不需要继续往后面走
{
if(i>1&&a[p][s].id==a[d[i-1]][j].id)continue;
if(i>2&&a[p][s].id==a[d[i-2]][k].id)continue;
if(i>3&&a[p][s].id==a[d[i-3]][l].id)continue;
if(i>4&&a[p][s].id==a[d[i-4]][r].id)continue;
dp[cnt][j][k][l][r]=max(dp[cnt^1][s][j][k][l]+a[p][s].x,dp[cnt][j][k][l][r]);//发现第s个是可以在第i天出现的故可以进行状态转移
}
}
else
{
dp[cnt][j][k][l][r]=max(dp[cnt^1][0][j][k][l],dp[cnt][j][k][l][r]);//这一天没有对手
}
}
cnt^=1;
}
int ans=0;
rep(j,6)
rep(k,6)
rep(l,6)
rep(r,6)
ans=max(ans,dp[cnt^1][j][k][l][r]);
printf("%.2lf\n",double (ans/100.0));
}
int main()
{
int t;
// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&g);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j].x);
a[i][j].id=j;
}
sort(a[i]+1,a[i]+1+n,cmp);//进行贪心的先决条件,,必须从大带小排序
}
g=g+10;
for(int i=1;i<=g;i++)
{
scanf("%d",&d[i]);
}
solve();
}
return 0;
}