ABC337D Cheating Gomoku Narabe 题解

My Blog

前言


比赛时曾因为复制相似代码未改变量名浪费了$15min$,在比赛结束前$15sec$因网络问题未提交成功。比赛以$900$分遗憾告终。


提交后又因数组问题$RE$,尝试多次才$AC$


思路


本题可以通过$\varTheta(HW)$的时间复杂度进行预处理。  
记录$num1,num2,num3,num4$四个行列前缀和数组。  
$num1_{i,j}:$$i$列中,第$1$$j$个字符中 .的个数。  
$num2_{i,j}$$j$列中,第$1$$i$个字符中的个数。  
$num3_{i,j}:$$i$列中,第$1$$j$个字符中 x 的个数。  
$num4_{i,j}:$$j$列中,第$1$$i$个字符中 x的个数。  
像前缀和一样推出每一项。  
                                         $num1_{i,j}=num1_{i-1,j}+ \begin{cases} 0\ s_{i,j}=.\\ 1\ s_{i,j}=o\\ 1\ s_{i,j}=x\\ \end{cases}$
        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        $num2_{i,j}=num2_{i,j-1}+ \begin{cases} 0\ s_{i,j}=.\\ 1\ s_{i,j}=o\\ 1\ s_{i,j}=x\\ \end{cases}$
        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        $num3_{i,j}=num3_{i-1,j}+ \begin{cases} 0\ s_{i,j}=x\\ 1\ s_{i,j}=o\\ 1\ s_{i,j}=.\\ \end{cases}$
        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        $num4_{i,j}=num4_{i,j-1}+ \begin{cases} 0\ s_{i,j}=x\\ 1\ s_{i,j}=o\\ 1\ s_{i,j}=.\\ \end{cases}$
然后对于数组a,b记录以(i,j)为第一项的行与列的最小修改次数。  
(若(i,j)为第一项的行与列中有 x,则值为-1)  
有转移式:  
$num3_{i,j+K-1}-num3{i,j-1}=0$时(这一段没有x )
         ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        $\underset{1 \le i \le H,1 \le j \le W-K+1}{a_{i,j}=num1_{i,j+K-1}-num1_{i,j-1}}$
$num4_{i+K-1,j}-num4_{i-1,j}=0$时(这一段没有x
                                        $\underset{1 \le i \le H -K+1,1 \le j \le W}{a_{i,j}=num2_{i+K-1,j}-num2_{i-1,j}}$


易错点


因为此处数组大小不是常量,
注意数组大小,当数组大小<0时,就会运行错误  
也可以用vector避免此类问题。
例如用这样的判断语句避免$W-N+1<0$$H-N+1<0$的问题  
 

if(w < n)   size1 = 1;
if(h < n)   size2 = 1;
int a[h][size1],b[size2][w],num1[h][w],num2[h][w],num3[h][w],num4[h][w];


code

for(int i = 0;i < h;i ++){
    for(int j = 0;j < w;j ++){
        int tmp1 = 0,tmp2 = 0;
        if(s[i][j] == '.')  tmp1 = 1;
        else if(s[i][j] == 'x') tmp2 = 1;
        if(j == 0){
            num1[i][j] = tmp1;
            num3[i][j] = tmp2;
        }
        else{
            num1[i][j] = num1[i][j - 1] + tmp1;
            num3[i][j] = num3[i][j - 1] + tmp2;
        }
    }
}
for(int i = 0;i < h;i ++){
    for(int j = 0;j < w;j ++){
        int tmp1 = 0,tmp2 = 0;
        if(s[i][j] == '.')  tmp1 = 1;
        else if(s[i][j] == 'x') tmp2 = 1;
        if(i == 0){
            num2[i][j] = tmp1;
            num4[i][j] = tmp2;
        }
        else{
            num2[i][j] = num2[i - 1][j] + tmp1;
            num4[i][j] = num4[i - 1][j] + tmp2;
        }
    }
}
for(int i = 0;i < h;i ++){
    for(int j = 0;j <= w - n;j ++){
        if(j == 0){
            if(num3[i][j + n - 1] == 0){   
                a[i][j] = num1[i][j + n - 1];
                ans = min(ans,a[i][j]);
            }
        }else{
            if(num3[i][j + n - 1] - num3[i][j - 1] == 0){
                a[i][j] = num1[i][j + n - 1] - num1[i][j - 1];
                ans = min(ans,a[i][j]);
            }
        }
    }
}
for(int j = 0;j < w;j ++){
    for(int i = 0;i <= h - n;i ++){
        if(i == 0){
            if(num4[i + n - 1][j] == 0){
                b[i][j] = num2[i + n - 1][j];
                ans = min(ans,b[i][j]);
            }
        }else{
            if(num4[i + n - 1][j] - num4[i - 1][j] == 0){
                b[i][j] = num2[i + n - 1][j] - num2[i - 1][j];
                ans = min(ans,b[i][j]);
            }
        }
    }
}
  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值