5811. 用三种不同颜色为网格涂色 力扣周赛(Hard) dfs+dp

题目描述:

给你两个整数 m 和 n 。构造一个 m x n 的网格,其中每个单元格最开始是白色。请你用 红、绿、蓝 三种颜色为每个单元格涂色。所有单元格都需要被涂色。

涂色方案需要满足:不存在相邻两个单元格颜色相同的情况 。返回网格涂色的方法数。因为答案可能非常大, 返回 对 109 + 7 取余 的结果。

示例 1:

输入:m = 1, n = 1
输出:3
解释:如上图所示,存在三种可能的涂色方案。

题源:https://leetcode-cn.com/problems/painting-a-grid-with-three-different-colors/

题解:https://leetcode-cn.com/problems/painting-a-grid-with-three-different-colors/solution/fei-chang-zhi-guan-de-dong-tai-gui-hua-b-f34f/

首先,因为m小,枚举列状态(m=1,状态数3;m=2,状态数3*2;m=3,状态数3*2*2;m=4,状态数3*2*2*2=24;m=5,状态数3*2*2*2*2=48),其实数字很小的

然后,dp[i][j]表示第i列为j状态时,方法数为多少,0<j<状态数-1,判断dp[i-1][ 0 ~(状态数-1)]能否转移,想法直观简单

注意点:数组要memset否则自己这里能过,但是测试会答案出错!!!!

代码:

class Solution {
public:
     vector<vector<int>> states;
     vector<int> substate;
     int M;
     void getstates(int k)
     {
        if(k==M+1)
        {
            states.push_back(substate);
            return;
        }
        for(int i=0;i<3;i++)
        {
            if(substate.size()==0) substate.push_back(i);
              else if (substate.back()!=i) substate.push_back(i);
                else continue;
            getstates(k+1);
            substate.pop_back();
        }
        return;
     }
     bool isok(int i,int j)
     {
         for(int k=0;k<M;k++)
          if (states[i][k]==states[j][k]) return false;
        return true;
     }

     int colorTheGrid(int m, int n) {
      M=m;
      getstates(1);  //利用DFS,得到所有状态
      int s=states.size();
      long long dp[1005][55];
      long long mod=1e9+7;   
      memset(dp,0,sizeof(dp));  //必须有,否则会出错
      for(int i=0;i<s;i++) dp[1][i]=1;
      for(int i=2;i<=n;i++)
      {
          for(int j=0;j<s;j++)    //枚举i类状态
            for(int k=0;k<s;k++)  //枚举i-1列状态
              if (isok(j,k))   //两种状态能不能相邻
                 dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
      }
     long long res=0;
    for(int i=0;i<s;i++)
        res=(res+dp[n][i])%mod;
    return res;
    }
};

 

posted on 2021-07-11 16:06  Yxter  阅读(177)  评论(0编辑  收藏  举报

导航