天天看點

【CodeForces 611C】New Year and Domino

題意

  h行w列的矩形格子,“." 代表空的,"#" 代表滿的,多米諾是 1*2 的長方體,現在放進格子,給你子矩形的左上角和右上角,問在子矩形裡共有多少種放一塊多米諾的方法。

分析

  如果是空的,我們存為a[i][j]=1;滿的為0。

  我們可以儲存 b[i][j] 表示前 i 行 j 列有多少種放法,遞推來求。

【CodeForces 611C】New Year and Domino

  要求的大矩形的放法總數,就是粉色+紫色+藍色+白色和紅色框框的放法。

b[i][j-1]就是粉色+紫色,b[i-1][j]就是粉色+藍色

b[i][j] += b[i][j-1] + b[i-1][j] -b[i-1][j-1]。

如果a[i][j]==1,b[i][j] += a[i][j-1]+a[i-1][j]。

  針對每個詢問:r1,c1到r2,c2 共有多少放法

【CodeForces 611C】New Year and Domino

ans += b[r2][c2] - b[r2][c1-1] - b[r1-1][c2] + b[r1-1][c1-1]。

接下來判斷邊界是否還有如圖中白色框框的,要減去。

r1到r2行,如果c1列為空,而c1-1列也為空,那就要減去,

c1到c2列,如果r1行為空,而r1-1行也為空,那也要減去。

代碼

#include <stdio.h>
#include <algorithm>
#define F(a,b,c) for(int a=b;a<=c;a++)
#define N 505
using namespace std;
int h,w,a[N][N],b[N][N],q,ans;
int r1,c1,r2,c2;
char ch;
int main()
{
    scanf("%d%d",&h,&w);
    F(i,1,h)F(j,1,w)
    {
        scanf(" %c",&ch);
        if (ch == '.')
            a[i][j]=1;
    }
    F(i,1,h)F(j,1,w)
    {
        b[i][j] = b[i][j-1] + b[i-1][j] - b[i-1][j-1];
        if (a[i][j])
            b[i][j] += a[i][j-1] + a[i-1][j];
    }
    scanf("%d",&q);
    F(i,1,q)
    {
        scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
        ans = b[r2][c2] - b[r2][c1-1] - b[r1-1][c2] + b[r1-1][c1-1];
        F(j,r1,r2)
        if (a[j][c1] && a[j][c1-1])
            ans--;

        F(j,c1,c2)
        if (a[r1][j] && a[r1-1][j])
            ans--;

        printf("%d\n",ans);
    }
    return 0;
}      

┆涼┆暖┆降┆等┆幸┆我┆我┆裡┆将┆ ┆可┆有┆謙┆戮┆那┆ ┆大┆始┆ ┆然┆

┆薄┆一┆臨┆你┆的┆還┆沒┆ ┆來┆ ┆是┆來┆遜┆沒┆些┆ ┆雁┆終┆ ┆而┆

┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆沒┆ ┆你┆

┆ ┆這┆ ┆試┆方┆在┆逃┆ ┆會┆ ┆在┆ ┆清┆來┆準┆ ┆沒┆有┆ ┆沒┆

┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆這┆ ┆晨┆ ┆的┆ ┆有┆來┆ ┆有┆

┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆這┆ ┆裡┆ ┆沒┆ ┆殺┆ ┆來┆ ┆ ┆來┆