Codeforces 611C

题目链接:http://codeforces.com/problemset/problem/611/C
C:
一个矩阵(500*500),有些障碍点和空格点。
现在可以放一种1*2的骨牌,骨牌只能放在空格点。
问对于(x1,y1,x2,y2)这个矩阵,有多少种合法的放骨牌的方式。

很明显的dp[x2][y2] + dp[x1][y1] - dp[x2][y1] - dp[x1][y2]的模式,因为骨牌横竖放置的不一样所以稍微调一下下标就可以。
一.
刚开始想的时候想一下子把二维的答案直接存下来,但显然这样子是没法递推的,所以只能横着算一遍纵着算一遍,不过就是这样相比一维的话,记录的是以i,j为右下角的横或纵的数量,也就是说表示的是一个矩形的,而一维的话表示的是一行或者一列的,所以说只需要在处理的时候,把横或者纵的那条边去掉就可以了,不要多减就可以了!!!

二.用一维前缀和优化的时候,居然卡在了一个坑上,即sum[x2]-sum[x1],而不是x1-1,太坑了,这bug很是不好找啊!!!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e2+10;
char a[maxn][maxn];
int n,m;
int sumrow[maxn][maxn],sumcol[maxn][maxn];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        scanf("%s",a[i]+1);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i][j]=='.'&&a[i][j-1]=='.'){
                sumrow[i][j]=sumrow[i][j-1]+1;
            }
            else sumrow[i][j]=sumrow[i][j-1];
        }
    }
    for(int j=1;j<=m;j++){
        for(int i=1;i<=n;i++){
            if(a[i][j]=='.'&&a[i-1][j]=='.'){
                sumcol[i][j]=sumcol[i-1][j]+1;
            }
            else sumcol[i][j]=sumcol[i-1][j];
        }
    }
    int q,x1,y1,x2,y2;scanf("%d",&q);
    while(q--){
        int sum=0;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        for(int i=x1;i<=x2;i++){
            sum+=sumrow[i][y2]-sumrow[i][y1];
        }
        for(int i=y1;i<=y2;i++){
            sum+=sumcol[x2][i]-sumcol[x1][i];
        }
        printf("%d\n",sum);
    }
    return 0;
}

二维的代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e2+10;
char a[maxn][maxn];
int n,m;
int sumrow[maxn][maxn],sumcol[maxn][maxn];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        scanf("%s",a[i]+1);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            sumrow[i][j]=sumrow[i][j-1]+sumrow[i-1][j]-sumrow[i-1][j-1];
            sumcol[i][j]=sumcol[i][j-1]+sumcol[i-1][j]-sumcol[i-1][j-1];
            if(a[i][j]=='.'&&a[i][j-1]=='.') sumrow[i][j]++;
            if(a[i][j]=='.'&&a[i-1][j]=='.') sumcol[i][j]++;
        }
    }

    int q,x1,y1,x2,y2;scanf("%d",&q);
    while(q--){
        int sum=0;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        sum+=sumrow[x2][y2]-sumrow[x1-1][y2]-sumrow[x2][y1]+sumrow[x1-1][y1];
        sum+=sumcol[x2][y2]-sumcol[x1][y2]-sumcol[x2][y1-1]+sumcol[x1][y1-1];
        printf("%d\n",sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值