Just another board game(hdu7067)

原题链接

题目描述

在这里插入图片描述

输入描述

在这里插入图片描述

输出描述

在这里插入图片描述

输入样例

3
2 2 2
1 2
2 1
2 2 1
1 2
2 1
2 3 2
1 3 2
3 2 1

输出样例

1
2
2

题目大意:棋盘上每个点上有不同的数字,在 k 个回合内,两名玩家 A B 分别可以选择将棋子在同一行上移动或同一列上移动,k 个回合后棋子所在位置的数字即为该盘得分。玩家 A 希望得分越大越好,玩家 B 希望得分越小越好,求当有 k 个回合时最终的得分是多少。

本题想要让自己的收益最大化的话,共有两种做法,以 A 为例:①走到当行最大的数值 ②使 B 能够走到的最小值最大;

因此本题实质是判断回合 k 的奇偶性(毕竟1e18的数据范围谁又会用别的方法呢 ),而当 k=1 或 k=2 时需要特殊判断,因为此时分别轮到 A B 玩家走出第一步也是最后一步,因此考虑的是收益最大化的第一种做法(毕竟最开始都喜欢赌一赌嘛 )。而当 k≥3 时,由于之后操作的相同性,因此可考虑收益最大化的第二种做法,即让最后一回合操作的玩家收益最小。

当然,由于该游戏时每回合内玩家都可以决定结束游戏,因此需记录下起始位置的数字,并在最终答案与起始数字中取最大值。因为当起始数字比最终结果更大时,玩家 A 可在起手时刻决定结束游戏并取得收益最大化。

参考代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e6+10;

ll row[N];//每行最大 
ll col[N];//每列最小 

int t,n,m;
int main(){
    
    
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll k,s,x;
	cin>>t;
	while(t--){
    
    
		memset(row,0,sizeof(row));
		memset(col,0x3f3f3f3f,sizeof(col));
		
		cin>>n>>m>>k;
		
		for(int i = 0; i < n; i++)
			for(int j = 0; j < m; j++){
    
    
				cin>>x;
				if(i == 0 && j == 0)
					s = x;
				row[i] = max(row[i], x);
				col[j] = min(col[j], x);
			}
		
		if(k==1)
			cout<<row[0]<<endl;
		else if(k==2){
    
    
			ll ans = 0;
			for(int i = 0; i < m; i++)
				ans = max(col[i], ans);
			cout<<max(ans,s)<<endl;
		}
		else if(k%2==1){
    
    
			ll ans = 0x3f3f3f3f;
			for(int i = 0; i < n; i++)
				ans = min(ans, row[i]);
			cout<<max(ans,s)<<endl;
		}
		else if(k%2==0){
    
    
			ll ans = 0;
			for(int i = 0; i < m; i++)
				ans = max(col[i], ans);
			cout<<max(ans,s)<<endl;
		}
	}
	
	return 0;
}

Guess you like

Origin blog.csdn.net/laysan/article/details/119808675