Gym 101652W:Grid Coloring 动态规划DP

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

Catalog

      • Catalog
        • Problem:Portal
      • Solution:
        • AC_Code:
        • Problem Description:

Problem:Portal

 PDF链接:here
 原题目描述在最下面。
 给你一个 n×m(30×30) n × m ( 30 × 30 ) 矩阵, R R 代表红色, B B 代表蓝色。规定从左上角到每一个 B B 格子的地方必须都是 B B ,给你一个残图,你可以再 . . 处填任意颜色,问有多少种填法合法?

Solution:

状态表示:
dp[i][j] d p [ i ] [ j ] 表示第 i i 行第 j j 列处填 B B 色的合法方案数。 dp[i][0] d p [ i ] [ 0 ] 表示第 i i 行全填 R R 色的合法方案数。
如果给的图合法,那么怎么样都有一种合法的填法,就是把可以填 R R 的地方全部填 R R
转移方程:
dp[i][j]=dp[i1][k]k[j,m] d p [ i ] [ j ] = ∑ d p [ i − 1 ] [ k ] k ∈ [ j , m ]
因为如果 i i j j 列填 B B 色,那么这一个矩阵全都是 B B 色了,这时的合法状态数可由 jm j − m 列累加得到。

内容参考:shili_xu

有些细节处理请看代码。

哦对了,你要先把可以填的位置预处理出来。每读到一个 B B 就把 i×j i × j 矩阵全填 B B ,每读到一个 R R 就把 (i,j) ( i , j ) (n,m) ( n , m ) 全填 R R ,剩下的就是你可以填的位置。

比如第 i i 行可以在 st s t ed e d 内填色,那么可以用 dp[i][st1] d p [ i ] [ s t − 1 ] 表示这一行全部填 R R 色的方案等等。

AC_Code:

#include
#define mme(a,b) memset((a),(b),sizeof((a))) 
using namespace std;
typedef long long LL;
const int N = 3e1 + 7;
const int M = 1e5 + 7;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;

char ar[N][N];
int is[N][N];
LL dp[N][N];
int n,m;

int main(){
  while(~scanf("%d%d", &n, &m)){
    int flag=1;
    for(int i=0;iscanf("%s",ar[i]);
      if(flag==0)continue;
      for(int j=0;jif(ar[i][j]=='B'){
          for(int a=0;a<=i;++a){
            for(int b=0;b<=j;++b){
              if(ar[a][b]=='R')flag=0;
              ar[a][b]='B';
            }
          }
        }
      }
    }
    if(flag==0){
      printf("0\n");
      continue;
    }else if(ar[n-1][m-1]=='B'){
      printf("1\n");
      continue;
    }
    mme(is,0);
    int sa=INF,sb=INF,tot=0;
    for(int i=0;ifor(int j=0;jif(ar[i][j]=='R'){
          sb=min(sb,j);//sa=min(sa,i);
        }else if(ar[i][j]=='.'){
          if(j1][j+1]=1;
          }
        }
      }
    }
    //以上预处理is[][],is[i][j]等于1表示可以填B或R
    mme(dp, 0);
    for(int i=1;i<=n;++i){
      int p = -1;
      for(int j=1;j<=m;++j){
        if(is[i][j]==1){
          if(p == -1)p = j-1;
          for(int k=j;k<=m;++k){
            dp[i][j] += dp[i-1][k];
          }
          dp[i][j] = max(dp[i][j], 1LL);
        }
      }
      if(p == -1){
        for(int k=0;k<=m;++k)dp[i][m]+=dp[i-1][k];
      }else{
        for(int k=p;k<=m;++k)dp[i][p]+=dp[i-1][k];
        dp[i][p] = max(dp[i][p], 1LL);
      }
    }
    LL sum = 0;
    for(int i=n;i>=1;--i){
      for(int j=0;j<=m;++j)sum+=dp[i][j];
      if(sum)break;
    }
    sum = sum>0?sum:1LL;//答案和1LL去max
    printf("%lld\n", sum);
  }
  return 0;
}


Problem Description:

Gym 101652W:Grid Coloring 动态规划DP_第1张图片
Gym 101652W:Grid Coloring 动态规划DP_第2张图片

你可能感兴趣的:(基础DP/背包DP,ACM算法之旅)