Comet OJ - Contest #3 B -棋盘 (思维+分类讨论)

题目描述

 

小猫有一个 2\times N2×N 的棋盘,每一个格子放着一个黑棋子或白棋子。

小熊觉得小猫的棋盘不够好看,想要把棋盘上的一部分白棋子替换成黑棋子,使得所有黑棋子都能够在仅允许上下左右四个方向走,且仅经过黑棋子在的格子的情况下两两互相到达。

小熊想知道至少要将多少个白棋子替换成黑棋子。

注意:不能将黑棋子替换成白棋子。

 

 
 

输入描述

 

第一行有一个正整数 NN (1 \le N \le 10^51N105)。

接下来两行,每行 NN 个整数,描述整个棋盘。若第 ii 行的第 jj 个整数是 00,代表棋盘 (i,j)(i,j) 的位置放着白棋子,若是 11 则放着黑棋子。

数据保证至少存在一个黑棋子。

 

输出描述

 

输出一行包含一个整数,表示答案。

 

样例输入 1 

3
1 0 0
0 0 1

样例输出 1

2

样例输入 2 

5
0 1 0 1 0
0 0 1 0 0

样例输出 2

1

提示

样例一中可以将第一行的两个白棋子替换成黑棋子。

样例二中可以将位置 (1, 3)(1,3) 的白棋子换成黑棋子。

 

思路:

由于题目说这个矩阵只有两行,我们知道,对于每一列,2块方格,有4个组合方式,

有1的列,只有以下三个方式是可能需要变化前面的白棋子的。

分别是:

两个1

上0下1

上1下0

 

如果是两个1,我们可以从上一个有1的位置,直线连接过来到当前的一个1,记上一个1出来的位置是last 

则对答案的贡献是 i-last-1 

如果上1下0,我们需要根据last位置的1是什么情况,。如果上行有1,那么贡献是  i-last-1 否则是 i-last

上0下1 和上面一样来处理即可。

每遇到一列有1就去维护 last 和 1在上还是在下的信息Pos

 

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int a[maxn][4];
int n;
int main()
{

    //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
    //freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
    gbtb;
    cin>>n;
    int r=-1;
    int l=inf;
    repd(j,0,1)
    repd(i,1,n)
    {
        cin>>a[i][j];
        if(a[i][j])
        {
            r=max(r,i);
            l=min(l,i);
        }
    }
    int last=l;
    int pos;
    if(a[l][0]==a[l][1])
    {
        pos=2;
    }else if(a[l][0])
    {
        pos=0;
    }else
    {
        pos=1;
    }
    int ans=0;
    // cout<<l<<" "<<r<<endl;
    repd(i,l+1,r)
    {
        if(a[i][0]||a[i][1])
        {
            if(a[i][0]==a[i][1])
            {
                pos=2;
                ans+=i-last-1;
            }else if(a[i][0])
            {
                if(pos==0)
                {
                    pos=0;
                    ans+=i-last-1;
                }else if(pos==1)
                {
                    pos=2;
                    ans+=i-last;
                }else
                {
                    pos=0;
                    ans+=i-last-1;
                }
            }else if(a[i][1])
            {
//                db(pos);
                if(pos==1)
                {
                    pos=1;
                    ans+=i-last-1;
                }else if(pos==0)
                {
//                    db(last);
                    ans+=i-last;
                    pos=2;
                }else
                {
                    pos=1;
                    ans+=i-last-1;
                }
            }
            last=i;
        }
    }
    cout<<ans<<endl;
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}

 

转载于:https://www.cnblogs.com/qieqiemin/p/10864748.html

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值