poj 1579(记忆化搜索)DP
2012-03-15 23:33
323 查看
Consider a three-parameter recursive function w(a, b, c):
if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 1
if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: w(20, 20, 20)
if a < b and b < c, then w(a, b, c) returns: w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)
otherwise it returns: w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)
这本身就是一个递归函数,要是按照函数本身写递归式,结果肯定是TLE,这里我开了一个三维数组,从w(0,0,0)开始递推,逐步产生到w(20,20,20)的值,复杂度O(n^3).
总结:这道题是很地道的DP,因为它的子问题实在是太多了,所以将问题的结果保存起来,刘汝佳《算法艺术和信息学竞赛》中115页讲到自底向上的递推,这个例子就非常典型。总体来说这个题目还是非常简单的,不过这个思想是地道的动态规划。
#include<stdio.h>
#include<math.h>
int w(int a,int b,int c)
{
if(a<=0||b<=0||c<=0)
return 1;
else if(a>20||b>20||c>20)
return 1048576;
else if(a==c||a==b||b==c)
return pow(2,a);
else if(a<b&&b<c)
return w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c);
else
return w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
int main()
{
int a,b,c,d;
while(scanf("%d%d%d",&a,&b,&c)!=-1,a!=-1||b!=-1||c!=-1)
{
d=w(a,b,c);
printf("w(%d, %d, %d) = %d\n",a,b,c,d);
}
return 0;
}
以为是个水题,看来并不水啊!还是用三维数组存储吧,总结:能用递推就不能用递归!超时的严重啊!
下面的是AC代码:
#include<stdio.h>
int main()
{
int a,b,c,i,j,k,w[20][20][20];
for(i=0;i<20;i++)
for(j=0;j<20;j++)
for(k=0;k<20;k++)
{
if(i==0||j==0||k==0)
w[i][j][k]=1;
else if(i<j&&j<k)
w[i][j][k]=w[i][j][k-1]+w[i][j-1][k-1]-w[i][j-1][k];
else
w[i][j][k]=w[i-1][j][k]+w[i-1][j-1][k]+w[i-1][j][k-1]-w[i-1][j-1][k-1];
}
while(scanf("%d%d%d",&a,&b,&c)!=-1,a!=-1||b!=-1||c!=-1)
{
if(a<=0||b<=0||c<=0)
printf("w(%d, %d, %d) = 1\n",a,b,c);
else if(a>=20||b>=20||c>=20)
printf("w(%d, %d, %d) = 1048576\n",a,b,c);
else
printf("w(%d, %d, %d) = %d\n",a,b,c,w[a][b][c]);
}
return 0;
}
if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 1
if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: w(20, 20, 20)
if a < b and b < c, then w(a, b, c) returns: w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)
otherwise it returns: w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)
这本身就是一个递归函数,要是按照函数本身写递归式,结果肯定是TLE,这里我开了一个三维数组,从w(0,0,0)开始递推,逐步产生到w(20,20,20)的值,复杂度O(n^3).
总结:这道题是很地道的DP,因为它的子问题实在是太多了,所以将问题的结果保存起来,刘汝佳《算法艺术和信息学竞赛》中115页讲到自底向上的递推,这个例子就非常典型。总体来说这个题目还是非常简单的,不过这个思想是地道的动态规划。
#include<stdio.h>
#include<math.h>
int w(int a,int b,int c)
{
if(a<=0||b<=0||c<=0)
return 1;
else if(a>20||b>20||c>20)
return 1048576;
else if(a==c||a==b||b==c)
return pow(2,a);
else if(a<b&&b<c)
return w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c);
else
return w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
int main()
{
int a,b,c,d;
while(scanf("%d%d%d",&a,&b,&c)!=-1,a!=-1||b!=-1||c!=-1)
{
d=w(a,b,c);
printf("w(%d, %d, %d) = %d\n",a,b,c,d);
}
return 0;
}
以为是个水题,看来并不水啊!还是用三维数组存储吧,总结:能用递推就不能用递归!超时的严重啊!
下面的是AC代码:
#include<stdio.h>
int main()
{
int a,b,c,i,j,k,w[20][20][20];
for(i=0;i<20;i++)
for(j=0;j<20;j++)
for(k=0;k<20;k++)
{
if(i==0||j==0||k==0)
w[i][j][k]=1;
else if(i<j&&j<k)
w[i][j][k]=w[i][j][k-1]+w[i][j-1][k-1]-w[i][j-1][k];
else
w[i][j][k]=w[i-1][j][k]+w[i-1][j-1][k]+w[i-1][j][k-1]-w[i-1][j-1][k-1];
}
while(scanf("%d%d%d",&a,&b,&c)!=-1,a!=-1||b!=-1||c!=-1)
{
if(a<=0||b<=0||c<=0)
printf("w(%d, %d, %d) = 1\n",a,b,c);
else if(a>=20||b>=20||c>=20)
printf("w(%d, %d, %d) = 1048576\n",a,b,c);
else
printf("w(%d, %d, %d) = %d\n",a,b,c,w[a][b][c]);
}
return 0;
}
相关文章推荐
- poj 1088滑雪(记忆化搜索, dp)
- DP 记忆化搜索 poj 1088
- poj 3280 dp 记忆化搜索
- 记忆化搜索(DP)—— Balance (POJ 1837)
- POJ 3252 Round Numbers(数位dp && 记忆化搜索)
- hdoj 1028/poj 2704 Pascal's Travels(记忆化搜索||dp)
- poj 1579 Function Run Fun(记忆化搜索)
- POJ 1958 Strange Towers of Hanoi (四塔问题,线性dp,记忆化搜索)
- poj Function Run Fun(DP)(记忆化搜索)
- POJ 1579-Function Run Fun(记忆化搜索-递归)
- POJ 1579 Function Run Fun【记忆化搜索】
- POJ 3252 Round Numbers(数位dp&记忆化搜索)
- poj 1088/nyoj 10 滑雪(记忆化搜索/DP)
- POJ 1579/hrbust 1029/哈理工oj 1029 Function Run Fun【记忆化搜索】
- POJ 1579 Function Run Fun【记忆化搜索】
- HDU 1331 poj 1579记忆化搜索
- poj-1976 A Mini Locomotive(DP,记忆化搜索)
- poj 1243 One Person(dp,记忆化搜索)
- poj1179 区间dp(记忆化搜索写法)有巨坑!
- poj 1579 Function Run Fun ( 记忆化搜索 )