算法基礎:1枚舉

枚舉是基於已有的知識進行答案猜測的一種問題求解策略。通常是根據建立的數學模型中的一組變量及其條件,在條件允許的範圍內對變量依次取值,判斷所取的值是否滿足數學模型中的條件,直到找到(全部)符合條件的值爲止。
*使用時注意以下三方面的問題:
1、建立簡潔的數學模型。數學模型中變量的數量要儘量少,它們之間相互獨立。
2、減小搜索的空間。利用已有的知識,縮小數學模型中各個變量的取值範圍,避免不必要的計算。
3、採用合適的搜索順序。對搜索空間的遍歷順序要與數學模型中的條件表達式一致。


             例題:稱硬幣
  問題描述
  賽利有12枚銀幣。其中有11枚真幣和1枚假幣。假幣看起來和真幣沒有區別,但是重量不同。但賽利不知道假幣比真幣輕還是重。於是他向朋友借了一架天平。朋友希望賽利稱三次就能找出假幣並且確定假幣是輕是重。例如:如果賽利用天平稱兩枚硬幣,發現天平平衡,說明兩枚都是真的。如果賽利用一枚真幣與另一枚銀幣比較,發現它比真幣輕或重,說明它是假幣。經過精心安排每次的稱量,賽利保證在稱三次後確定假幣。
  輸入格式
  第一行有一個數字n,表示有n組測試用例。對於每組測試用例:輸入有三行,每行表示一次稱量的結果。賽利事先將銀幣標號爲A-L。每次稱量的結果用三個以空格隔開的字符串表示:天平左邊放置的硬幣 天平右邊放置的硬幣 平衡狀態。其中平衡狀態用”up”, “down”, 或”even”表示, 分別爲右端高、右端低和平衡。天平左右的硬幣數總是相等的。
  輸出要求
  輸出哪一個標號的銀幣是假幣,並說明它比真幣輕還是重(heavy or light)。
  輸入樣例
  1
  ABCD EFGH even 
  ABCI EFJK up 
  ABIJ EFGH even
  輸出樣例
  K is the counterfeit coin and it is light.

解題思路
具體實現時,要注意兩點:
(1) 選擇合適的算法
對於每一枚硬幣x 逐個試探:
x 比真幣輕的猜測是否成立?猜測成立則進行輸出。
這裏寫代碼片x 比真幣重的猜測是否成立?猜測成立則進行輸出。
(2) 選擇合適的數據結`這裏寫代碼片構
以字符串數組存儲稱量的結果。每次稱量時,天平左右最多有6 枚硬幣。因此,字符串的長度需要爲7,最後一位存儲字符串的結束符’\0’,便於程序代碼中使用字符串操作函數。
char left[3][7], right[3][7], result[3][7];


參考代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
char left[3][7], right[3][7], result[3][5];

bool isHeavy(char x);
bool isLight(char x);
int main(void)
{
int i,n;
char c;
scanf("%d", &n);
while ( n > 0 )
{
for ( i = 0; i < 3; i++ )
scanf("%s %s %s", left[i], right[i], result[i]);
for ( c = 'A'; c <= 'L'; c++ )
{
if ( isLight(c) )
{
printf("%c is the counterfeit coin and it is light.\n", c);
break;
}
if ( isHeavy(c) )
{
printf("%c is the counterfeit coin and it is heavy.\n", c);
break;
}
}
n--;
}
return 0;
}

bool isLight( char x ) // 判斷硬幣x 是否爲輕的代碼
{
int i;
for ( i = 0; i < 3; i++ ) // 判斷是否與三次稱量結果矛盾
switch( result[i][0] )
{
case 'u': if( strchr(right[i], x) == NULL )
return false;
break;
case 'e': if(strchr(right[i], x) != NULL ||
strchr(left[i], x) != NULL)
return false;
break;
case 'd': if(strchr(left[i], x) == NULL)
return false;
break;
}
return true;
}

bool isHeavy( char x ) //判斷硬幣x 是否爲重的代碼
{
int i;
for ( i = 0; i < 3; i++ ) // 判斷是否與三次稱量結果矛盾
switch( result[i][0] )
{
case 'u': if( strchr(left[i], x) == NULL)
return false;
break;
case 'e': if(strchr(right[i], x) != NULL || strchr(left[i], x) != NULL)
return false;
break;
case 'd': if(strchr(right[i], x) == NULL)
return false;
break;
}
return true;
}
發佈了36 篇原創文章 · 獲贊 12 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章