聰明學生問題代碼

這個代碼結構並不複雜,大家可以直接複製下來運行。大家在看代碼之前請先自行了解什麼是聰明學生問題.

來看一下整體代碼

# 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函數可以處理大小順序不一的兩種情況.
並且我的程序也能打印出每次遞歸的情況,看一下運行截圖
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章