zoukankan      html  css  js  c++  java
  • CF991D Bishwock

    CF991D Bishwock

    题目描述

    给一个(2 imes n)的网格,上面一些位置以及被覆盖上了。现在你有一种形状为L的小块,每个由三个小格组成,构成L型
    现在问你,当前的网格最多还能摆多少小块(不能覆盖以及覆盖过的格子)

    输入格式

    两行两个字符串由(X,0)组成,(X)表示被覆盖了,(0)表示还没有

    输出格式

    一行 一个整数

    样例输入

    00X00X0XXX0
    0XXX0X00X00
    

    样例输出

    4
    

    对于(100)%的数据满足(nle 10^5)

    题目分析

    ​ 大约一年前的模拟赛上似乎就出过这道题。(考试后证明我是对的......) 至于为什么要更这篇题解,因为今年差点没切(去年都切了.... 其实最后今年也没切,数组开小了)

    ​ 个人想法就不说了,乱七八糟想了一堆,一个没搞出来。周围大佬们都切了,就先去看T2了(事实证明是正确的,如果T1切掉也就不会那么认真的去考虑T2)。

    ​ 闲话少叙,步入正题。

    ​ 首先我们观察一下数据范围....(然鹅并没有什么用) 突破口是在(2 imes n)的矩阵,以及只有一种L型的块块。 所以,对于一个(2 imes 2)的矩阵,合法情况是一定的。具体几种长什么样可以手画一下。

    ​ 所以我们想到一种类似递推的更新方式。 预处理出来每列的状态:

    (f[i][1/2/3/4])分别表示每列的一种可能更新的状态。

    (f[i][1]) (XX) (f[i][2]) (0X) (f[i][3])$ X0 $ (f[i][4]) (00)

    (f[i][0])用来记录当前列的答案。

    ​ 然后就是一堆特判。 注意对于每列更新完之后,(f[i][2/3])这两种情况需要清零,而(f[i-1][4]=1)(f[i][4]=1)时,(f[i][4])只会被用到一次,所以可以拆成(f[i][2/3] = 1)以便接下来的操作。具体实现见代码。

    ​ code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N = 100020;
    int f[N][5];
    char str[3][N];
    int main()
    {
    	// freopen("a.in", "r", stdin);
    	// freopen("a.out", "w", stdout);
    	scanf("%s", str[1] + 1);
    	scanf("%s", str[2] + 1);
    	int n = strlen(str[1] + 1);
    	memset(f, -1, sizeof f);
    	for(int i = 1 ; i <= n ; i ++)
    		f[i][0] = 0;
    	for(int j = 1 ; j <= n ; j ++)
    	{
    		if(str[1][j] == '0' && str[2][j] == '0')
    			f[j][4] = 1;
    		else
    			if(str[1][j] == '0' && str[2][j] == 'X')
    				f[j][3] = 1;
    		else
    			if(str[1][j] == 'X' && str[2][j] == '0')
    				f[j][2] = 1;
    		else
    			if(str[1][j] == 'X' && str[2][j] == 'X')
    				f[j][1] = 1;
    	}
    	for(int i = 2 ; i <= n ; i ++)
    	{
    		if(f[i - 1][4] == 1 && f[i][4] == 1)
    		{
    			f[i][0] ++;
    			f[i][2] = 1;
    			f[i][3] = 1;
    			f[i][4] = 0;
    		}
    		else
    			if(f[i - 1][2] == 1 && f[i][4] == 1)
    			{
    				f[i][0] ++;
    				f[i][4] = 0;
    			}
    		else
    			if(f[i - 1][3] == 1 && f[i][4] == 1)
    			{
    				f[i][0] ++;
    				f[i][4] = 0;
    			}
    		else
    			if(f[i - 1][4] == 1 && f[i][3] == 1)
    			{
    				f[i][0] ++;
    				f[i][3] = 0;
    			}
    		else
    			if(f[i - 1][4] == 1 && f[i][2] == 1)
    			{
    				f[i][0] ++;
    				f[i][2] = 0;
    			}
    	}
    	int ans = 0;
    	for(int i = 1 ; i <= n ; i ++)
    		ans += f[i][0];
    	printf("%d", ans);
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

  • 相关阅读:
    基于Tags实现内容推荐的方法(代码)
    洞察未来
    技术人员工作原则
    罗辑思维CEO脱不花:关于工作和成长,这是我的121条具体建议
    王兴:8年时间,我对商业的思考
    100个管理定律
    李想:关于工作和成长,这是我的100条具体建议 |【经纬低调分享】
    C++--win32
    谈谈javaSE中的==和equals的联系与区别
    Vue 基础知识
  • 原文地址:https://www.cnblogs.com/0724-zcsblog/p/11732722.html
Copyright © 2011-2022 走看看