A. Subrectangle Guess
题意:给定一个各个位置数字不相同的n * m的矩阵,Michael和Joe玩一个游戏,首先Michael选择一个h,和一个w。Joe选择矩阵上一个h * w的子矩阵。如果Michael能猜中所选子矩阵中的最大值,则Michael赢得游戏。Michael想要选取尽量小的h和w,使得无论Joe选择什么,他都能猜中。
思路:找到最大值所在的最大子矩阵面积。
AC code:
#include <bits/stdc++.h>
using namespace std;
int n,m,a[50][50];
void solve(){
cin>>n>>m;
int x=0,y=0;
int mx=-0x3f3f3f3f;//最开始赋值为0,没有注意数据范围,后来才发现>=-1e9,哭死。
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]>mx){
x=i;
y=j;
mx=a[i][j];
}
}
}
int ans=0;
ans=max(ans,(abs(x-1)+1)*(abs(y-1)+1));
ans=max(ans,(abs(x-n)+1)*(abs(y-1)+1));
ans=max(ans,(abs(x-1)+1)*(abs(y-m)+1));
ans=max(ans,(abs(x-n)+1)*(abs(y-m)+1));
cout<<ans<<endl;
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
B. Circle Game
题意:n个堆形成一个环,每一个堆上有a[i]个石子,从第一个堆开始,A和B每次可以去掉当前堆中任意数目的石子,然后移动到下一个堆,一个堆不能连续操作。从A开始,直到谁当前堆为0时,谁就输。
思路:若n为奇数,则A一定赢,A每次可以把堆中的石子全部删除,下一次轮到这个堆时一定是B且该堆石子数为0。若n为偶数,则A只能对奇数堆操作,B只能对偶数堆操作,那么最优策略就是每次只去掉堆中的一个石子,分别求奇数堆和偶数堆中石子数最小值,谁小谁输,如果相等,谁在前谁输。
AC code:
#include <bits/stdc++.h>
using namespace std;
int n,a[60];
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(n&1){
cout<<"Mike"<<endl;
}else{
int mn1=0x3f3f3f3f,pos1=0,mn2=0x3f3f3f3f,pos2=0;
for(int i=1;i<=n;i+=2){
if(a[i]<mn1){
mn1=a[i];
pos1=i;
}
}
for(int i=2;i<=n;i+=2){
if(a[i]<mn2){
mn2=a[i];
pos2=i;
}
}
if(mn1==mn2){
cout<<(pos1<pos2?"Joe":"Mike")<<endl;
}else{
cout<<(mn1<mn2?"Joe":"Mike")<<endl;
}
}
}
return 0;
}
C. Zero Path
题意:给出n行m列的矩阵,每一个方格要么为1,要么为-1,一次只能向右或者向上移动一个单位,从左上角走到右下角,问走过的路径遇到的数目之和是否可以为0。
思路:用dp分别求从左上角到右下角的数目之和最大值和最小值,判断0是否在这两者之间即可。
AC code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[1010][1010],dp[1010][1010],dp1[1010][1010];
signed main(){
int t;
cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
if((n+m)%2==0){
cout<<"NO"<<endl;
continue;
}
dp[1][0]=dp[0][1]=dp1[1][0]=dp1[0][1]=0;
for(int i=2;i<1010;i++){
dp[i][0]=-1e17;
dp[0][i]=-1e17;
dp1[i][0]=1e17;
dp1[0][i]=1e17;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j];
dp1[i][j]=min(dp1[i-1][j],dp1[i][j-1])+a[i][j];
}
}
if(dp[n][m]>=0 && dp1[n][m]<=0){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
return 0;
}