
UVA1379
定义:
为对战第支队伍时,胜率排名第位的棒球手的胜率
为第天的对手
为考虑到前天时,第天派出胜率排名第位,第天派出第位,第天派出第位,第天派出第位选手时的最大期望值。因为选手比赛后需要至少4天,所以需要4天的派遣情况才能去重并使状态唯一。
转移方程:
如果第天有比赛,则枚举第个人应该派遣谁,并选取由最优的子状态转移过来。(因为选手休息4天又能上场了,所以枚举到排名第5就可以了。比如选手第一天上场,然后第二到五天休息,第六天又能重新上场了,一到五天五个人)。如果第i天没有比赛,则以存储中的最优状态。
去重:
为了防止选手在5天内重复上场,在每考虑第i场比赛的人选时,要保证第i场比赛的选手在第场比赛中未出场过。定义返回在面对编号为的对手时,排名第的选手的。去重详见代码。
滚动数组优化:
这道题的空间卡的严,如果定义会爆空间,因此需要优化。可以发现中不是就是,明显的滚动数组优化。
AC代码:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
constexpr static int inf = 0x3f3f3f3f;
int N, M, G, D;
struct Node{
int ID, Val;
bool operator<(const Node& Right)const {
return this->Val > Right.Val;
}
}Map[101][101];
int Schedule[211];
int dp[2][6][6][6][6];
void Input() {
scanf("%d%d%d", &N, &M, &G);
for (int i = 1; i <= M; ++i) {
for (int j = 1; j <= N; ++j) {
scanf("%d", &Map[i][j].Val);
//记录选手ID,用于去重
Map[i][j].ID = j;
}
//将面对第i名对手时的选手按胜率降序排列
sort(Map[i] + 1, Map[i] + N + 1);
}
D = G + 10;
for (int i = 1; i <= D; ++i) {
scanf("%d", &Schedule[i]);
}
return;
}
//如果Index是0,返回一个不存在的ID,使循环继续
int GetPitcher(int Opponent, int Index) {
if (!Index) {
return 0;
}
return Map[Opponent][Index].ID;
}
double DP() {
memset(dp[0], 0x0, sizeof(dp[0]));
for (int i = 1; i <= D; ++i) {
int
&& Cur = i & 1,//等价于i
&& Pre = 1 - Cur;//等价于i-1
memset(dp[Cur], 0x0, sizeof(dp[Cur]));
if (Schedule[i]) {
for (int a = 1; a <= 5; ++a) {
for (int b = 0; b <= 5; ++b) {
//如果第i场比赛派第a名选手,那就不能和第i-1场比赛时决定的第b名选手ID相同,即去重
if (i > 1 && GetPitcher(Schedule[i], a) == GetPitcher(Schedule[i - 1], b)) {
continue;
}
for (int c = 0; c <= 5; ++c) {
if (i > 2 && GetPitcher(Schedule[i], a) == GetPitcher(Schedule[i - 2], c)) {
continue;
}
for(int d = 0; d <= 5; ++d) {
if (i > 3 && GetPitcher(Schedule[i], a) == GetPitcher(Schedule[i - 3], d)) {
continue;
}
for (int e = 0; e <= 5; ++e) {
if (i > 4 &&
GetPitcher(Schedule[i], a) == GetPitcher(Schedule[i - 4], e)) {
continue;
}
dp[Cur][a][b][c][d] = max(
dp[Cur][a][b][c][d],
dp[Pre][b][c][d][e] + Map[Schedule[i]][a].Val
);
}
}
}
}
}
}
else {
for (int a = 0; a <= 5; ++a) {
for (int b = 0; b <= 5; ++b) {
for (int c = 0; c <= 5; ++c) {
for (int d = 0; d <= 5; ++d) {
dp[Cur][0][a][b][c] = max(
dp[Cur][0][a][b][c],
dp[Pre][a][b][c][d]
);
}
}
}
}
}
}
int
&& Ans = 0,
&& Cur = D & 1;
for (int a = 0; a <= 5; ++a) {
for (int b = 0; b <= 5; ++b) {
for (int c = 0; c <= 5; ++c) {
for (int d = 0; d <= 5; ++d) {
Ans = max(Ans, dp[Cur][a][b][c][d]);
}
}
}
}
return Ans / 100.;
}
int main() {
int T;
cin >> T;
while (T--) {
Input();
printf("%.2lf\n", DP());
}
return 0;
}
浙公网安备 33010602011771号