这个代码结构并不复杂,大家可以直接复制下来运行。大家在看代码之前请先自行了解什么是聪明学生问题.
来看一下整体代码
# include <stdlib.h>
//找出t2--t1最小提问次数
int step(int t1,int t2)
{
if(t2 > t1)
{
return t2-t1;
}
else
{
return 3+t2-t1;
}
}
void array_print(int temp[3])
{
int z;
for(z=0;z<3;z++)
{
printf("%d ",temp[z]);
}
}
//教授提问多少次t3能正确回答问题
int times(int i,int j,int t1,int t2,int t3)
{
int k,z;
int temp[3] ={0};
k=i-j;
if(k==0)
{
return t3;
}
if(k>0)
{
temp[t2-1] = j;
temp[t3-1] = i-j;
temp[t1-1] = i;
array_print(temp);
printf("\n");
return times(j,i-j,t2,t3,t1)+step(t1,t3);//此时t1最大,加上t1到t3的步数,
}
if(k<0)
{
temp[t2-1] = j;
temp[t3-1] = j-i;
temp[t1-1] = i;
array_print(temp);
printf("\n");
return times(i,j-i,t1,t3,t2)+step(t2,t3);//此时t2最大,加上t2到t3的步数,
}
}
int main()
{
int result;
int a=1,b=2,c=3;
int arr[3] = {3,8,5}; 存三个学生代表的值
int index = 0;
int max_num = -1,mid_num = -1;
int max_index = -1,mid_index = -1;
for(;index<3;index++)
{
if(max_num<arr[index])
{
max_num = arr[index];
max_index = index;
}
}
for(index = 0;index<3;index++)
{
if(mid_num < arr[index]&&arr[index]!=max_num)
{
mid_num = arr[index];
mid_index = index;
}
}
c = max_index+1;
b = mid_index+1;
if((c==1&&b==2)||(c==2 && b==1))
{
a=3;
}
else if((c==2 && b==3)||(c==3 && b==2))
{
a=1;
}
else
{
a=2;
}
printf("推导过程:\n");
array_print(arr);
printf("\n");
result=times(arr[a-1],arr[b-1],a,b,c);//ab谁前谁后无所谓,只要找到正确的最大值和ab正确座标即可
printf("第%d位学生",c);
printf("在第%d次提问时回答正确\n",result);
return 0;
}
arr数组存储的就是三个学生代表的值,下标也就是代表学生序号
首先我们要找到值最大的学生的下标和值,然后我的程序里还找出了值居中的学生的下标和值,但其实这是没有必要的。我们只需找到值最大的学生的下标和数组即可。
这个问题还有一些前提,就是一定时值最大的学生先猜出自己的值,至于这是为什么,大家可以把它当成规律,其实自己多试机组数据也能发现这个现象。所以其实我们只要让程序帮我们找到值最大的学生在第几次提问中猜出自己的值即可。
看一下times函数
int times(int i,int j,int t1,int t2,int t3)
{
int k,z;
int temp[3] ={0};
k=i-j;
if(k==0)
{
return t3;
}
if(k>0)
{
temp[t2-1] = j;
temp[t3-1] = i-j;
temp[t1-1] = i;
array_print(temp);
printf("\n");
return times(j,i-j,t2,t3,t1)+step(t1,t3);//此时t1最大,加上t1到t3的步数,
}
if(k<0)
{
temp[t2-1] = j;
temp[t3-1] = j-i;
temp[t1-1] = i;
array_print(temp);
printf("\n");
return times(i,j-i,t1,t3,t2)+step(t2,t3);//此时t2最大,加上t2到t3的步数,
}
}
times函数前两个参数为值较小的学生的值,t1,t2,表示值为i,j的学生的下标,t3就是当前最大值学生的下标,为什么说是当前最大值,因为times函数的原理是通过递归,一层一层往上走,知道出现两个较小值相同的情况。这里放一张老师给的视频截图供大家理解
拿 3 5 8 举例,用3-5得出5更大,此时就假设5位最大值,此时3还是3,t3就变成了5-3,因为要满足最大值为另外两个值之和。此时t3猜出自己值的次数就等于3 5 2 情况下t2(5)猜出自己值的次数加上从t2提问到t3的次数.因为我们要解出额情况是3 5 8的情况,我们只是把他转化成了3 5 8 的情况。 所以还要加上t2到t3的提问次数
但我们还是不知道352 的情况t2会在第几次猜出自己的值。所以就这样一直递归到1 1 2的情况,此时就是 t3在第三次猜出自己的值。
另外我们看到times函数里有if判断k>0 和k<0两种情况,所以我们其实没必要找到中间值的学生下标,即我们没有让times函数里的前两个函数按一定的大小顺序传入,因为times函数可以处理大小顺序不一的两种情况.
并且我的程序也能打印出每次递归的情况,看一下运行截图