其他分享
首页 > 其他分享> > CodeForces - 598E 记忆化搜素实现dp

CodeForces - 598E 记忆化搜素实现dp

作者:互联网

链接:https://vjudge.net/contest/308522#problem/A

题意:题目大意:一块n*m的巧克力,要吃掉k块。我们通过沿横线或者竖线划分巧克力的方式来得到k块巧克力。沿横线分割巧克力的代价是巧克力的横线长的平方(j2j2),沿竖线分割巧克力的代价是巧克力的竖线长的平方(i2i2),问要吃到k块巧克力的代价最小是多少。

这道题可以看作是一道裸题,他的状态很容易设定,显然的话我们设置状态为dp[x][y][k]表示有一块大小为x*y的巧克力然后我们要吃掉k块。然后我们想转移的话接下来我们就按横着切和竖着切分别不同枚举。枚举分界点和每一段要切的次数。。。。。。

复杂度的话有点玄学,反正是o(能过)。。。。。。。。。。。。。。。。。。。。。。。

但是这个按照常规转移方式的话我们很难对其进行转移,所以我们得换一种方式。我们用记忆化搜素的方式对其进行转移,这样的话就会方便我们转移很多。。。。。。。。。。。。

然后并没有什么复杂的,主要是要注意一点,就是注意缓存(即dp[x][y][k]!=-1) return; 和边界条件的判断。。。。。

还有数组呀要开大一点,我开小了wa了。。。。。。。。。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <bitset>
 5 #include <algorithm>
 6 #include <iostream>
 7 typedef long long ll;
 8 using namespace std;
 9 int dp[35][35][55];
10 int t,n,m,k;
11 
12 int solve(int x,int y,int num){
13   //  printf("%d  %d %d\n",x,y,num);
14     if(dp[x][y][num]!=-1) return dp[x][y][num];
15     if(x*y==num||num==0){//边界条件判定
16         dp[x][y][num]=0;//这儿要附值
17         return 0;
18     }
19     if(x*y<num) return (int)1e7;//边界条件判定
20     int ans=(int)1e7;
21     //横着
22     for(int i=1;i<x;i++){
23         for(int j=0;j<=num;j++){
24             ans=min(ans,y*y+solve(i,y,j)+solve(x-i,y,num-j));
25         }
26     }
27     //竖着
28     for(int i=1;i<y;i++){
29         for(int j=0;j<=num;j++){
30             ans=min(ans,x*x+solve(x,i,j)+solve(x,y-i,num-j));
31         }
32     }
33     return dp[x][y][num]=ans;
34 }
35 
36 int main(){
37     memset(dp,-1,sizeof(dp));
38     solve(32,32,52);//打表的话要打大一点点。。。。。。。。
39     //或者不用打表的方式,直接在里面进行函数调用。。。。。
40     //也没有什么区别,反而更保险一点。。。。。。
41     scanf("%d",&t);
42     while(t--){
43         scanf("%d%d%d",&n,&m,&k);
44         printf("%d\n",dp[n][m][k]);
45     }
46     return 0;
47 }
View Code

 

标签:巧克力,return,int,CodeForces,num,搜素,include,dp
来源: https://www.cnblogs.com/pandaking/p/11118648.html