题目描述
输入描述
输出描述
输入样例
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;
}