一道有意思的题,高手进来看看.

whhif 2003-04-20 07:20:31
有这样的一个函数.
w(a,b,c)
当a<0或b<0或c<0时.
返回1
当a>20或b>20或c>20时
返回w(20,20,20)
当a<b且b<c时
返回w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, 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)

我们可能用递归来做题.
但是要花的时间会很多,比如a=15,b=15,c=15时.

现在我们要在3秒内做出答案.

每行输入三个数,用空格格开
最后以-1 -1 -1 结束输入.
1 1 1
2 2 2
10 4 6
50 50 50
-1 7 18
-1 -1 -1
输出以下列形式:
w(1, 1, 1) = 2
w(2, 2, 2) = 4
w(10, 4, 6) = 523
w(50, 50, 50) = 1048576
w(-1, 7, 18) = 1

-----------------------------------------------------------
以下是我的做法:
以空间来换取时间.
#include <iostream>
#include <vector>

class tri
{
public:
tri(int x,int y,int z):a(x),b(y),c(z){}
tri():a(0),b(0),c(0){}
int a,b,c;
};
using namespace std;

int main()
{
vector<tri> input;
vector<tri> ::iterator p;
tri temp;
vector<int> result;

int base[21][21][21];
for(int i=0;i<21;i++)
for(int j=0;j<21;j++)
for(int k=0;k<21;k++)
{
if(i==0||j==0||k==0)
base[i][j][k]=1;
else if(i<j&&j<k)
{
base[i][j][k]=base[i][j][k-1]+base[i][j-1][k-1]-base[i][j-1][k];
}
else
{
base[i][j][k]=base[i-1][j][k]+base[i-1][j-1][k]+base[i-1][j][k-1]-base[i-1][j-1][k-1];
}
}
int a,b,c;
while(true)
{
cin>>a;
cin>>b;
cin>>c;
if(a==-1&&b==-1&&c==-1)
{
break;
}
else
{
input.push_back(tri(a,b,c));
}
}
for(p=input.begin();p!=input.end();++p)
{
temp=*p;
if(temp.a<0)
{
temp.a=0;
}
if(temp.b<0)
{
temp.b=0;
}
if(temp.c<0)
{
temp.c=0;
}
if(temp.a>20)
{
temp.a=20;
temp.b=20;
temp.c=20;
}
result.push_back(base[temp.a][temp.b][temp.c]);
}
int size=input.size();
for(int i=0;i<size;i++)
{
cout<<"w("<<input[i].a<<", "<<input[i].b<<", "<<input[i].c<<" )"<<" = "<<result[i]<<endl;
}
return 0;
}


但我不知道还有什么情况我还没有考虑到.
请大家帮我想想,谢谢.
...全文
44 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
delphihero 2003-04-22
  • 打赏
  • 举报
回复
a = 21,c = -1,条件就没说明这中情况如何处理,程序怎么写也没办法
whhif 2003-04-22
  • 打赏
  • 举报
回复
TO iceheart(冷酷的心)
你说的情况就是我没有想到的,谢谢.

我想在出现在这种情况之后就不能用数组来做了.
有谁会动态归划的来做做吧.
Behard 2003-04-22
  • 打赏
  • 举报
回复
无聊
iceheart 2003-04-22
  • 打赏
  • 举报
回复
a = 21,c = -1时按哪个条件判断啊?
whhif 2003-04-22
  • 打赏
  • 举报
回复
还顶
whhif 2003-04-22
  • 打赏
  • 举报
回复
看来,我得每天顶一次啊.
iceheart 2003-04-22
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#include "windows.h"

int array[21][21][21] = {0};

int flag[21][21][21] = {0};

int WW(int a, int b, int c)
{

if ( a < 0 || b < 0 || c < 0 ) {

return 1;
}

if ( a > 20 || b > 20 || c > 20 ) {

return WW( 20, 20, 20);
}
if (flag[a][b][c]) return array[a][b][c];

if ( a < b && b < c ) {

array[a][b][c] = WW( a, b, c - 1) + WW( a, b - 1, c - 1 ) - WW( a - 1, b - 1, c - 1 );

flag[a][b][c] = 1;

return array[a][b][c];
}

array[a][b][c] = WW( a - 1, b, c ) + WW(a - 1, b - 1, c ) + WW ( a - 1, b, c - 1 ) - WW( a - 1, b - 1, c - 1 );

flag[a][b][c] = 1;

return array[a][b][c];
}

int main(int argc, char **argv)
{
int a, b, c;

if (argc != 4) return 0;

a = atoi(argv[1]);

b = atoi(argv[2]);

c = atoi(argv[3]);

SYSTEMTIME currtime;

GetSystemTime(&currtime);

printf("%d\n",WW(a,b,c));//

SYSTEMTIME newtime;

GetSystemTime(&newtime);

int usesecond = (int)(newtime.wMinute * 60000) + (int)(newtime.wSecond * 1000) + (int)(newtime.wMilliseconds) - (int)(currtime.wMinute * 60000) - (int)(currtime.wSecond * 1000) + (int)(currtime.wMilliseconds);

printf("\n用时%d毫秒",usesecond);

return 0;
}


楼主的算法应该考虑将a,b,c 为-1的情况存入数组,数组应该是array[22][22][22],
int *base = &array[1][1][1],
base[-1][-1~20][-1~20] = 1;
base[-1~20][-1][-1~20] = 1;
base[-1~20][-1~20][-1] = 1;
我的图省事用递归了。
Chrisma 2003-04-21
  • 打赏
  • 举报
回复
递归加动态规划可提高效率。
动态规划用三维数组,每个元素为一结构:
struct ELEM{
int flag; //是否已计算过
long Value;
};
递归过程中先看一个元素是否计算过,如计算过就不计算了。
linchwu 2003-04-21
  • 打赏
  • 举报
回复
有点小问题,
我做好了在帖上来.up
linchwu 2003-04-21
  • 打赏
  • 举报
回复
w(0,0,0) 照道理应该是w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1) 即 w(-1,0, 0)+w(-1,-1,0)+w(-1.0,-1)-w(-1,-1,-1)=2 是吧?

但是你的结果好像是1.
whhif 2003-04-21
  • 打赏
  • 举报
回复
关键是连生成数据都有问题
我接着顶.
delphihero 2003-04-21
  • 打赏
  • 举报
回复
其实用 template 就是在编译时期,就把计算的数值存入到了数组,用模板的递归取代了循环而已,生成base[21][21][21]和 whhif 的是一样的,呵呵函数还是用的你的,不过是把运行时刻的计算放到了编译时刻。数据少效率能高一些,取值时控制好边缘就行了。
这样编译速度跟空间损失就大了,不是很要求效率用循环很好的,计算数据也用不了1秒,足够满足条件了
shefj123 2003-04-21
  • 打赏
  • 举报
回复
这个问题我也是粗略地看了一下。我个人想法是这样的,如果想弄清这个问题是否考虑完整,可采用边缘检测值的形式去判断,对于这个问题的边缘是0和20,那么我们可以用0、-1、1、19、20和21等数的组合去进行判断。看能否解决问题。
当然这仅仅我个人的想法而已,也许与当前算法不相符,仅供楼主参考而已。^_^
whhif 2003-04-21
  • 打赏
  • 举报
回复
//不好意思,上面的程序我贴的时候贴错了.现在纠正!!!!!


#include <iostream>
#include <vector>

class tri
{
public:
tri(int x,int y,int z):a(x),b(y),c(z){}
tri():a(0),b(0),c(0){}
int a,b,c;
};
using namespace std;

int main()
{
vector<tri> input;
vector<tri> ::iterator p;
tri temp;
vector<int> result;

int base[21][21][21];
for(int i=0;i<21;i++)
for(int j=0;j<21;j++)
for(int k=0;k<21;k++)
{
if(i==0||j==0||k==0)
base[i][j][k]=1;
else if(i<j&&j<k)
{
base[i][j][k]=base[i][j][k-1]+base[i][j-1][k-1]-base[i][j-1][k];
}
else
{
base[i][j][k]=base[i-1][j][k]+base[i-1][j-1][k]+base[i-1][j][k-1]-base[i-1][j-1][k-1];
}
}
int a,b,c;
while(true)
{
cin>>a;
cin>>b;
cin>>c;
if(a==-1&&b==-1&&c==-1)
{
break;
}
else
{
input.push_back(tri(a,b,c));
}
}
for(p=input.begin();p!=input.end();++p)
{
temp=*p;
if(temp.a<0||temp.b<0||temp.c<0)//不好意思,这个地方打错了.
{
temp.a=0;
temp.b=0;
temp.c=0;
}
if(temp.a>20)
{
temp.a=20;
temp.b=20;
temp.c=20;
}
result.push_back(base[temp.a][temp.b][temp.c]);
}
int size=input.size();
for(int i=0;i<size;i++)
{
cout<<"w("<<input[i].a<<", "<<input[i].b<<", "<<input[i].c<<" )"<<" = "<<result[i]<<endl;
}
return 0;
}
用户 昵称 2003-04-21
  • 打赏
  • 举报
回复
搬个凳子等着高手。
fantasy1983 2003-04-21
  • 打赏
  • 举报
回复
==研究中
oyd 2003-04-21
  • 打赏
  • 举报
回复
我有一个快速的算法。
建立一个文件,先把结果写进去。以后运行时像查表一样
whhif 2003-04-21
  • 打赏
  • 举报
回复
#include <iostream>
#include <vector>

class tri
{
public:
tri(int x,int y,int z):a(x),b(y),c(z){}
tri():a(0),b(0),c(0){}
int a,b,c;
};
using namespace std;

int main()
{
vector<tri> input;
vector<tri> ::iterator p;
tri temp;
vector<int> result;

int base[21][21][21];
for(int i=0;i<21;i++)
for(int j=0;j<21;j++)
for(int k=0;k<21;k++)
{
if(i==0||j==0||k==0)
base[i][j][k]=1;
else if(i<j&&j<k)
{
base[i][j][k]=base[i][j][k-1]+base[i][j-1][k-1]-base[i][j-1][k];
}
else
{
base[i][j][k]=base[i-1][j][k]+base[i-1][j-1][k]+base[i-1][j][k-1]-base[i-1][j-1][k-1];
}
}
int a,b,c;
while(true)
{
cin>>a;
cin>>b;
cin>>c;
if(a==-1&&b==-1&&c==-1)
{
break;
}
else
{
input.push_back(tri(a,b,c));
}
}
for(p=input.begin();p!=input.end();++p)
{
temp=*p;
if(temp.a<0||temp.b<0||temp.c<0)
{
temp.a=0;
temp.b=0;
temp.c=0;
}
if(temp.a>20)
{
temp.a=20;
temp.b=20;
temp.c=20;
}
result.push_back(base[temp.a][temp.b][temp.c]);
}
int size=input.size();
for(int i=0;i<size;i++)
{
cout<<"w("<<input[i].a<<", "<<input[i].b<<", "<<input[i].c<<" )"<<" = "<<result[i]<<endl;
}
return 0;
}
它用上面的数据,
应输出:
w(1, 1, 1) = 2
w(2, 2, 2) = 4
w(10, 4, 6) = 523
w(50, 50, 50) = 1048576
w(-1, 7, 18) = 1
----------------------------------------------------------------
大家来做做试试.
whhif 2003-04-21
  • 打赏
  • 举报
回复
TO delphihero(阿蒙(C++))
非常感谢你的帮助,但我不能确定你的程序在某些情况(数据)下还正确.
不过你的C++水平真是很高.不容易了.
但我的程序也不是运行了很长时间.可能我又贴错了,再贴一遍.

TO linchwu()
因为我的程序中用了
if(a<0||b<0||c<0)
{
temp.a=0;
temp.b=0;
temp.c=0;
}
而且还有:

for(int i=0;i<21;i++)
for(int j=0;j<21;j++)
for(int k=0;k<21;k++)
{
if(i==0||j==0||k==0)

//请看这里,就是这里,i==0||j==0||k==0,base[i][j][k]=1;//

base[i][j][k]=1;
else if(i<j&&j<k)
{
base[i][j][k]=base[i][j][k-1]+base[i][j-1][k-1]-base[i][j-1][k];
}
else
{
base[i][j][k]=base[i-1][j][k]+base[i-1][j-1][k]+base[i-1][j][k-1]-base[i-1][j-1][k-1];
}
}


因此,也就相当于
对w(a,b,c)这个函数来说:
当a<=0或b<=0或c<=0时
返回1;
这也是我在题中没有说清楚的.不好意思,不过它也在程序中体现了也来.
w(0,0,0)=1
而不是你说的那样.
whhif 2003-04-21
  • 打赏
  • 举报
回复
我自已顶一下吧,
有没有高手啊.
加载更多回复(5)

70,037

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧