• 「模拟8.23」阴阳 DP


    对于此题的性质我们考虑DP

    分四种情况

    黑色块在右侧单调降,单调升

    还有在左侧

    另外我们这样可能会记重,所以还要将重复记过的也就是边界线是横的和竖的

    然后还要将全白全黑加上

      1 #include<bits/stdc++.h>
      2 #define MAXN 2100
      3 #define int long long
      4 using namespace std;
      5 int f[5][MAXN][MAXN];
      6 int sum[5][MAXN][MAXN];
      7 int n,m;
      8 const int mod=1e9+7;
      9 char c[MAXN][MAXN];
     10 int jud[2][MAXN][MAXN];
     11 int jud_sum[2][MAXN][MAXN];
     12 void work(int k,int cal)
     13 {    
     14     f[k][0][m]=1;
     15     for(int i=1;i<=n;++i)//黑色单降靠左
     16     {
     17         sum[k][i-1][m]=f[k][i-1][m];
     18         for(int j=m-1;j>=0;--j)
     19         {
     20            sum[k][i-1][j]=(sum[k][i-1][j+1]+f[k][i-1][j])%mod;
     21            //printf("sum[%lld][%lld][%lld]=%lld
    ",k,i-1,j,sum[k][i-1][j]);
     22         }
     23         for(int j=0;j<=m;++j)
     24         {  
     25             //printf("i%lld j=%lld jud%lld %lld
    ",i,j,jud[cal][i][j],(jud[cal^1][i][m]-jud[cal^1][i][j]));
     26             if(j!=0)
     27                 if(jud[cal][i][j]!=0||(jud[cal^1][i][m]-jud[cal^1][i][j])!=0){continue;}
     28             if(j==0)
     29                 if(jud[cal][i][j]||jud[cal^1][i][m]){continue;}
     30                 f[k][i][j]=sum[k][i-1][j]%mod;
     31             //printf("f[%lld][%lld][%lld]=%lld
    ",k,i,j,f[k][i][j]);
     32         }
     33     }
     34     f[k+1][0][0]=1;
     35     for(int i=1;i<=n;++i)//黑色单升靠左
     36     {
     37         sum[k+1][i-1][0]=f[k+1][i-1][0];
     38         for(int j=1;j<=m;++j)
     39         {
     40            sum[k+1][i-1][j]=(sum[k+1][i-1][j-1]+f[k+1][i-1][j])%mod;
     41         }
     42         for(int j=0;j<=m;++j)
     43         {  
     44             if(j)
     45                 if(jud[cal][i][j]||(jud[cal^1][i][m]-jud[cal^1][i][j]))continue;
     46             if(j==0)
     47                 if(jud[cal][i][j]||jud[cal^1][i][m])continue;
     48             f[k+1][i][j]=sum[k+1][i-1][j]%mod;
     49             //printf("f[%lld][%lld][%lld]=%lld
    ",k+1,i,j,f[k+1][i][j]);
     50         }
     51     }
     52 }
     53 int ans=0;
     54 int get_sum(int k,int x1,int y1,int x2,int y2)
     55 {
     56     if(x1>x2)return 0;if(y1>y2)return 0;
     57     return (jud_sum[k][x2][y2]-jud_sum[k][x1-1][y2]-jud_sum[k][x2][y1-1]+jud_sum[k][x1-1][y1-1]+mod)%mod;
     58 }
     59 void work2()
     60 {
     61      for(int i=0;i<=n;++i)
     62      {
     63          if(get_sum(1,1,1,i,m)==0&&get_sum(0,i+1,1,n,m)==0)
     64          {
     65              ans--;
     66          }
     67      }
     68      for(int i=0;i<=n;++i)
     69      {
     70          if(get_sum(0,1,1,i,m)==0&&get_sum(1,i+1,1,n,m)==0)
     71          {
     72              ans--;
     73          }
     74      }
     75      for(int i=0;i<=m;++i)
     76      {
     77          if(get_sum(0,1,1,n,i)==0&&get_sum(1,1,i+1,n,m)==0)
     78          {
     79              ans--;
     80          }
     81      }
     82      for(int i=0;i<=m;++i)
     83      {
     84          if(get_sum(1,1,1,n,i)==0&&get_sum(0,1,i+1,n,m)==0)
     85          {
     86              ans--;
     87          }
     88      }     
     89      if(get_sum(1,1,1,n,m)==0)ans++;
     90      if(get_sum(0,1,1,n,m)==0)ans++;
     91 }
     92 signed main()
     93 {
     94     scanf("%lld%lld",&n,&m);
     95     for(int i=1;i<=n;++i)
     96     {
     97         scanf("%s",c[i]+1);
     98         for(int j=1;j<=m;++j)
     99         {
    100             jud[0][i][j]+=jud[0][i][j-1];
    101             jud[1][i][j]+=jud[1][i][j-1];
    102             jud_sum[0][i][j]=(jud_sum[0][i-1][j]+jud_sum[0][i][j-1]-jud_sum[0][i-1][j-1])%mod;
    103             jud_sum[1][i][j]=(jud_sum[1][i-1][j]+jud_sum[1][i][j-1]-jud_sum[1][i-1][j-1])%mod;            
    104             if(c[i][j]=='B'){jud[0][i][j]++;jud_sum[0][i][j]++;}
    105             if(c[i][j]=='W'){jud[1][i][j]++;jud_sum[1][i][j]++;}
    106         }
    107     }
    108     work(1,1);
    109     work(3,0);
    110     for(int k=1;k<=4;++k)
    111     {
    112         for(int i=0;i<=m;++i)
    113         {
    114             ans=(ans+f[k][n][i])%mod;
    115             //printf("f[%lld][%lld][%lld]=%lld
    ",k,n,i,f[k][n][i]);
    116         }
    117     }
    118     //printf("初ans=%lld
    ",ans);
    119     work2();
    120     printf("%lld
    ",ans%mod);
    121 }
    View Code
  • 相关阅读:
    并查集 示例 : poj 1703 [Find them, Catch them 帮派之争]
    《Python 第五章》条件,循环和其他语句
    《Python 第一章》基础知识
    heapSort 堆排序 / 二叉堆
    并查集 hdu 1856 示例
    KMP / hdu 1711 [找到匹配的位置并返回]
    《Python 第四章》字典
    EnumChildWindows的使用
    C#查找指定窗口的子窗口的句柄
    C#里字符串取左边N个字符,右边N个字符,从中间取N个字符的函数
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11420961.html
Copyright © 2020-2023  润新知