动态规划的一道题目,首先按照题意,依次存储信息,然后对于每一个对手而言,由于每个投手在参赛之后要休息四天,所以每个对手应该存储胜算最大的前5个投手,因为处于最大化胜算期望的条件下,要同时保证至少有一个投手能对抗该对手。在所有的存储操作结束之后就开始进行动态规划,每次在进行当前的这一天的投手的选择的时候要回推四天再进行状态转移,逐天枚举得出最优值,同时要区分开是否当天是否存在比赛,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
using namespace std;
class record{
public:
int id;
int value;
};
bool compare(const record& a,const record& b){
return a.value > b.value;
}
class Solve{
public:
int n, m, g;
int percent[110][110];
vector<int> infor[110];
int dp[2][5][5][5][5];//i-3,i-2,i-1,i
int season[220];
void Init(){
for (int i = 1; i <= m; i++){
infor[i].clear();
vector<record> R;
for (int j = 1; j <= n; j++){
cin >> percent[i][j];
record temp;
temp.id = j;
temp.value = percent[i][j];
R.push_back(temp);
}
sort(R.begin(),R.end(),compare);
for (int t = 0; t < 5; t++)
infor[i].push_back(R[t].id);
}
infor[0].clear();
infor[0].push_back(0);
for (int i = 0; i < g + 10; i++)
cin >> season[i];
}
void Deal(){
Init();
memset(dp, -1, sizeof(dp));
int now = 1, last = 0;
dp[last][0][0][0][0] = 0;
for (int i = 0; i < g + 10; i++){
memset(dp[now], -1, sizeof(dp[now]));
int a = i - 1 >= 0 ? season[i - 1] : 0;
int b = i - 2 >= 0 ? season[i - 2] : 0;
int c = i - 3 >= 0 ? season[i - 3] : 0;
int d = i - 4 >= 0 ? season[i - 4] : 0;
int cur = season[i];
if (cur != 0){//当前是存在比赛的
for (int x = 0; x < infor[cur].size(); x++){
int take_part = infor[cur][x];
for (int y = 0; y < infor[a].size();y++){//第i-1天
if (infor[a][y] == take_part) continue;
for (int z = 0; z < infor[b].size(); z++){//第i-2天
if (infor[b][z] == take_part) continue;
for (int k = 0; k < infor[c].size(); k++){//第i-3天
if (infor[c][k] == take_part) continue;
for (int h = 0; h < infor[d].size(); h++){//第i-4天
if (infor[d][h] == take_part) continue;
if (dp[last][h][k][z][y] == -1) continue;
dp[now][k][z][y][x] = max(dp[now][k][z][y][x], dp[last][h][k][z][y] + percent[cur][take_part]);
}
}
}
}
}
}
else{//当前是不存在比赛的
for (int y = 0; y < infor[a].size(); y++){//第i-1天
for (int z = 0; z < infor[b].size(); z++){//第i-2天
for (int k = 0; k < infor[c].size(); k++){//第i-3天
for (int h = 0; h < infor[d].size(); h++){//第i-4天
if (dp[last][h][k][z][y]!=-1)
dp[now][k][z][y][0] = max(dp[now][k][z][y][0],dp[last][h][k][z][y]);
}
}
}
}
}
now ^= 1;
last ^= 1;
}
int ans = -1;
for (int i = 0; i < 5; i++){
for (int j = 0; j < 5; j++){
for (int k = 0; k < 5; k++){
for (int m = 0; m < 5; m++){
ans = max(ans, dp[last][i][j][k][m]);
}
}
}
}
printf("%0.2f\n",ans/100.0);
}
};
int main(){
Solve a;
int t;
cin >> t;
while (t--){
cin >> a.n >> a.m >> a.g;
a.Deal();
}
return 0;
}