UVA 1379 Pitcher Rotation

这篇博客介绍了一道动态规划题目——UVA 1379 Pitcher Rotation。文章阐述了如何根据比赛规则,存储每个投手的信息,并确保每个对手面对至少一个可用的、胜算最大的投手。通过动态规划和回推四天的状态转移,逐步枚举以找到最优解决方案。详细实现代码在文中给出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划的一道题目,首先按照题意,依次存储信息,然后对于每一个对手而言,由于每个投手在参赛之后要休息四天,所以每个对手应该存储胜算最大的前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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值