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