Codeforces Round #801 (Div. 2) and EPIC Institute of Technology Round(A-C)题解

A. Subrectangle Guess

题目链接:Problem - A - Codeforces

题意:给定一个各个位置数字不相同的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

题目链接:Problem - B - Codeforces

题意: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

题目链接:Problem - C - Codeforces

题意:给出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;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值