切披萨的方案数

给你一个 rows x cols 大小的矩形披萨和一个整数 k ,矩形包含两种字符: 'A' (表示苹果)和 '.' (表示空白格子)。
你需要切披萨 k-1 次,得到 k 块披萨并送给别人。
切披萨的每一刀,先要选择是向垂直还是水平方向切,再在矩形的边界上选一个切的位置,将披萨一分为二。
如果垂直地切披萨,那么需要把左边的部分送给一个人,如果水平地切,那么需要把上面的部分送给一个人。
在切完最后一刀后,需要把剩下来的一块送给最后一个人。
请你返回确保每一块披萨包含 至少 一个苹果的切披萨方案数。

1. 记忆化搜索

class Solution {
public:
    const int MOD = 1e9 + 7;
    int ways(vector<string>& pizza, int k) {
        //求方案数目,一共有k-1刀的机会
        //可以选择横刀和竖刀
        //分别有m-1和n-1个落刀位置
        //切到相同状态时,剩下的方案数相同的,这里可以考虑使用记忆化搜索
        int m = pizza.size();
        int n = pizza[0].size();
        int presum[m][n]; //记录右下角苹果数目
        memset(presum,0,sizeof(presum));
        //这里先预先计算每个点右下角的苹果数目
        for(int i=m-1;i>=0;i--){
            for(int j=n-1;j>=0;j--){
                if(pizza[i][j]=='A') presum[i][j]+=1;
                if(i!=m-1) presum[i][j]+=presum[i+1][j];
                if(j!=n-1) presum[i][j]+=presum[i][j+1];
                if(i!=m-1&&j!=n-1) presum[i][j]-=presum[i+1][j+1];
            }
        }

        int res = 0;
        int dp[m*n][k]; //记忆化搜索
        memset(dp,-1,sizeof(dp)); 
        function<int(int,int)> f = [&](int state, int times)->int{
            if(dp[state][times]!=-1) return dp[state][times];//记忆化搜索

            int x = state/n; int y = state%n;//上一次的落刀点
            if(times==k-1){//边界条件,切完了
                if(presum[x][y]>0) return dp[state][times] = 1;
                else return dp[state][times] = 0; 
            }

            int res = 0;//当前状态的方案数
            //横刀
            for(int i=x+1;i<m;i++){
                if(k-times>m+n-i-y) break;//剩余位置不够切,剪枝
                if(presum[x][y]-presum[i][y]==0) continue;//切除的部分不存在苹果
                res = (res + f(i*n+y,times+1))%MOD;
            }
            //竖刀
            for(int j=y+1;j<n;j++){
                if(k-times>m+n-j-x) break;//剩余位置不够切,剪枝
                if(presum[x][y]-presum[x][j]==0) continue;//切除的部分不存在苹果
                res = (res + f(x*n+j,times+1))%MOD;
            }
            return dp[state][times]=res;
        };
        return f(0,0);//初始状态为0,切了0刀
    }
};
posted @ 2023-08-17 01:06  失控D大白兔  阅读(41)  评论(0编辑  收藏  举报