权当抛砖引玉吧,掌握记搜的方法最重要。
#include#include #include using namespace std;int n,m,k;bool book[21][21];int cake[21][21];int dp[21][21][21][21];int yt(int x,int y,int w,int h)//返回蛋糕内樱桃值;x、y表示左上角坐标,w、h表示长和宽{ int yingtao=cake[x+w][y+h]-cake[x+w][y]-cake[x][y+h]+cake[x][y]; return yingtao;}int dfs(int x,int y,int w,int h)//开成int类型{ int ans=2147483647; if(dp[x][y][w][h]!=-1) return dp[x][y][w][h];//若x,y,w,h的状态已被搜过,则返回已经保存的结果 if(yt(x,y,w,h)==1) return 0;//樱桃值为1时,代价为0(不用再切了) if(yt(x,y,w,h)==0) return 214748364;//樱桃值为0时,代价无穷大;但在实现时,INF不能大于INT_MAX/2 for(int i=1;i
记忆化搜索,其实就是动态规划(DP)与搜索的完美结合,提高了搜索的效率,也提供了DP的道路。
所谓动态规划,就是动态的规划,其本质就是“状态转移”——从一种情况直接或间接推出其他情况。对于本题而言,就是要想清楚如何得到最小代价,是由哪几部分组成。
so本题具体操作如下:
定义一四维数组dp,存储在x,y,w,h的状态下的最小代价。
定义一int类型函数dfs,其返回值即为代价。若蛋糕已有解,则直接返回现有代价。否则若当前蛋糕内樱桃值为1,返回代价为0。若当前蛋糕内樱桃值为0,返回代价为“无穷大”。否则继续枚举可供下刀的行和列,继续对两侧进行搜索,打擂台寻找最小代价。遍历完所有情况后,保存当前结果并返回上一层。
小结:记忆化搜索与暴搜的最大区别在于,前者对搜索进行了优化,对当前结果进行了记录,避免了重复搜索。