100道动态规划——6 UVA 1629 Cake slicing 记忆化搜索

一道动态规划题,没什么可说的。

定义DP[i][j][k][l[]表示以i,j为顶点,长度为k宽度为l的蛋糕最少需要的代价。

对于一个dp[i][j][k][l]来说,你既可以横着切,也可以竖着切。状态转移方程有两个。

对于一个顶点在(row,col),长度为len,宽度为wid的矩形来说,

竖:dp[row][col][len][wid]=min(dp[row][col][len][wid],wid+dp[row][col][i][wid]+dp[row][col+i][len-i][wid]);

横:dp[row][col][len][wid]=min(dp[row][col][len][wid],len+dp[row][col][len][i]+dp[row+i][col][len][wid-i]);

然后走记忆化搜索就可以了。

不过在实际上写的时候还需要注意一个问题就是,判断切了之后的每个小矩形里面还有多少个樱桃,我这里在切之前会先判断一下,看看切了之后的两个小矩心是不是都有樱桃,用了一个二维的树状数组,但是实际上我觉得用二维前缀和更好,O(1)的时间嘛。我这里用二维树状数组主要是想练一练手。。

Tips:我这里的_insert()和__query()是用于树状数组的,getCheey()拿到一个矩形里面有多少个Cheey,_search用于记忆化搜索。

PS:樱桃的单词本来是Cherry,但是我记成了Cheey。。。。。好吧,大家将就着看一看吧。

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
typedef pair<int,int> pa;

int n,m,k,ca=1,arr[30][30][30][30],cheey[30][30],_search(int row,int col,int len,int wid);
pa te;
void _insert();
int _query(int row,int col),getCheey(int row,int col,int len,int wid);

int main(){
    while(scanf("%d%d%d",&n,&m,&k)!=EOF){
        memset(arr,0x3f,sizeof arr);
        for(int i=0;i<k;++i)
            scanf("%d%d",&te.first,&te.second),_insert();
        printf("Case %d: %d\n",ca++,_search(1,1,m,n));
        memset(cheey,0,sizeof cheey);
    }
    return 0;
}

int _search(int row,int col,int len,int wid){
    int &te=arr[row][col][len][wid];
    if(te!=0x3f3f3f3f)
        return te;
    if(getCheey(row,col,len,wid)==1)
        return te=0;

    for(int i=1;i<len;++i)
    if(getCheey(row,col,i,wid)&&getCheey(row,col+i,len-i,wid))
    te=min(te,wid+_search(row,col,i,wid)+_search(row,col+i,len-i,wid));

    for(int i=1;i<wid;++i)
    if(getCheey(row,col,len,i)&&getCheey(row+i,col,len,wid-i))
    te=min(te,len+_search(row,col,len,i)+_search(row+i,col,len,wid-i));

    return te;
}

void _insert(){
    for(int i=te.first;i<=n;i+=(i&-i))
    for(int j=te.second;j<=m;j+=(j&-j))
    ++cheey[i][j];
}

int _query(int row,int col){
    int ans=0;
    for(int i=row;i;i-=(i&-i))
    for(int j=col;j;j-=(j&-j))
    ans+=cheey[i][j];
    return ans;
}

int getCheey(int row,int col,int len,int wid){
    return _query(row+wid-1,col+len-1)+_query(row-1,col-1)-_query(row-1,col+len-1)-_query(row+wid-1,col-1);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值