http://poj.org/problem?id=1579
很水的一道小题儿,一开始算dp[][][]的时候顺序随便按照i,j,k一次递增的顺序进行,后来发现不可以~而且每一个dp到底需要哪些之前的dp也不是很容易看出来,还是用递归的顺序加上记忆搜索就简化许多
一开始的错误代码 :
#include<iostream>
using namespace std;
int dp[21][21][21];
int main(){
for(int i=0;i<=20;i++)
for(int j=0;j<=20;j++)
dp[0][i][j]=dp[i][0][j]=dp[i][j][0]=1;
for(int i=0;i<=20;i++)
for(int j=0;j<=20;j++)
for(int k=0;k<=20;k++){
if(i<j&&j<k)dp[i][j][k]=
dp[i][j][k-1]+dp[i][j-1][k-1]-dp[i][j-1][k];
else dp[i][j][k] = dp[i-1][j][k]+
dp[i-1][j-1][k]+dp[i-1][j][k-1]-dp[i-1][j-1][k-1];
}
int a,b,c;
while(cin>>a>>b>>c&&(a!=-1||b!=-1||c!=-1)){
int tempa,tempb,tempc;
tempa=(a<0)?0:a;
tempa=(a>20)?20:a;
tempb=(b<0)?0:b;
tempb=(b>20)?20:b;
tempc=(c<0)?0:c;
tempc=(c>20)?20:c;
cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<<dp[tempa][tempb][tempc]<<endl;
}
return 0;
}
更正后改成记忆化搜索的代码:
#include<stdio.h>
long num[21][21][21]={0};
long w(int a,int b,int c)
{
if(a<=0 || b<=0 || c<=0) return 1;
if(a>20 || b>20 || c>20) return w(20,20,20);
if(num[a][b][c]) return num[a][b][c];
if(a<b && b<c) return num[a][b][c]=(w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c));
return num[a][b][c]=(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 x,y,z;
while(scanf("%d%d%d",&x,&y,&z)!=EOF)
{
if(x==-1 && y==-1 && z==-1) return 0;
printf("w(%d, %d, %d) = %ld\n",x,y,z,w(x,y,z));
}
return 0;
}