謊言與誠實謎題

2021-08-26 01:35:42 字數 2913 閱讀 3141

一天,你跟隨漁夫出海打魚,在海上遇到了大風浪而迷失了方向,小船被刮到了一座小島上。島上有兩個相鄰的村子,乙個叫誠實村,乙個叫謊言村,誠實村的村民只會說真話,從不撒謊,而謊言村的村民則只說謊話,從不說真話。所以你決定想辦法區分出這不同的兩組人,弄清楚誰說的是真話,這樣才能夠找到回去的方向。這兩個村的村民很熱情,有問必答,你要求每位村民給你乙份他們認為是說謊者的名單。這些村民世世代代都生活在這裡,所以他們非常清楚誰在說謊。但是為了不得罪人,每位村民勉強地只給了你乙份不全的名單,當然這些名單也不能盡信。

你必須編寫乙個程式來篩選你所收集到的這些資訊,並判斷哪些村民是在說真話,哪些村民是在說謊話。兩個村的村民人數很多,所以你的程式必須能快速並有效的處理大量資料。

你的程式必須獲取乙個唯一的命令列引數,即檔案的名稱。開啟檔案並且解析裡面的資料。這些資料以村民的數量

n開頭,行尾另起一新行。後面跟著是連續的

n塊資訊,每塊資訊描述的是乙個村民所舉報的那些說謊者名單。每一塊的格式如下:

而後緊跟

m行,每一行包含乙個被舉報的人員名字。

accuser name和

m被一些製表符(tab)和空格隔開。

m總是在 [0,

n] 區間。所有人員的名字只包含字母且是唯一的並區分大小寫。

輸入檔案示例:

你的程式輸出必須由兩個數字組成,數字之間由乙個空格隔開,結尾另起一新行(換行符為 "

\n"),列印至標準輸出。第乙個數字是說謊者和誠實者中人數較多的一組人數; 第二個數字是人數較少的一組人數。我們保證這些測試資料只有乙個正確的解決方法。

輸出示例如下:

********************個人解決方案*************************==

/** * 因為題目沒有要求分清到底誰是真誰是假,只需要計算出對立雙方的人數 * 相互指認的雙方必定屬於對立的兩個陣營,所以說雙方只要有碰撞就說明分別屬於對立 * 假定第乙個屬於真話陣營,那麼他所指認的必定是假話陣營的, * 相反也成立,如果這個人是假話陣營,那麼他所指認的必定是真話陣營的 * 這樣我們可以構建乙個這樣的表結構 * a->b,c * b->a * c->a * 通過表可以確認那些人是相互對立的,通過遍歷表中的節點來確認具體屬於那個陣營 * 同時將已經確定屬於統一陣營的人儲存起來,減少遍歷的深度和次數來達到優化的目的 * 有三個輔助的列表:真話列表,假話列表,未決列表 * * 在第一遍對錶結構的遍歷不足以確定所有人的陣營時, * 通過不斷增加的真假話列表的含量來對未決列表中人員來確認其陣營 * (最差情況需要完全來通過未決列表來確定) * author cnsworder * mail [email protected] * 2010-07-19 */ #include #include #include #include #include using std::cin; using std::cout; using std::endl; using std::string; using std::ifstream; using std::list; //總人數 long usercount = 0; //假定的真話陣營的人數 long good_count = 0; //假定的假話陣營的人數 long bad_count = 0; //真話人名列表,用於遍歷對比 listtrue_users; //假話人名列表 listfalse_users; class user_info ; #pragma pack(0) /** * 相互對立的人的列表 */ //class bad_info ; //listt_bad; listusers; listtemps; int isgood(user_info name); void verify(); bool foreachlist(list::iterator b); /** * 假設第乙個為真的 * 統計說真話和假話的人數 */ void countbad() m++; for (; m != users.end(); m++) } else if (flag < 0) } } while(!temps.empty()) verify(); } /** * 驗證這個人是否已經確認說真話還是假話,否則,加入到未決佇列中,在後期驗證 * 根據返回值確定這個人屬於那種型別》0真話,<0假話, =0未決 */ int isgood(user_info user) } for (list::iterator g = false_users.begin(); g != false_users.end(); g++) } temps.push_back(user); return 0; } /** * 當系統積累一些資料後來辨識那些未決資料的狀況,通過遞迴來實現 * 如果隊列為空則停止遞迴,最差情況可能會陷入遞迴的死迴圈, * 但是根據題意所有的資料是可以確認的, * 並且隨著積累知識資料的增加這種情況出現這種情況會為零 */ void verify() for (list::iterator b = temps.begin(); b != temps.end(); b++) } } /** * 遍歷知識列表,確認則將增加對應計數器,並從未決列表中刪除,並返回true,否則返回false * 因為從列表中刪除list的iterator指標會自動增加1,

通過返回來確認繼續遍歷還是遞迴,直接通過判斷自增可以優化掉 */ bool foreachlist(list::iterator b) } for (list::iterator t = false_users.begin(); t != false_users.end(); t++) } } return false; } void readfile(char* filename) users.push_back(user); } } int main(int argc, char **argv) readfile(argv[argc - 1 ]); countbad(); if (good_count < bad_count) cout << good_count << " " << bad_count << endl; return 0; }

這個演算法不完善,時間有限,並且stl庫在有些系統上在遞迴時產生段錯誤。如果將佇列改為不能重複的在大資料量時會更好。大家幫忙看看有沒有更好的方案。

《誠實與信任》讀後感

前幾天,我們學習了 誠實與信任 這篇課文。讀完文中的故事,我不禁思緒萬千。其中,最讓我有感觸的是小紅車車主的一句話 不,人與人之間還有比金錢更重要的東西,你給我留下了誠實與信任,這比金錢更重要。上幼兒園的時候,爸爸 媽媽,還有老師就給我講過 狼和小羊 的故事,講 長鼻子 匹諾曹的故事 讓我明白 誠實...

EII的謊言與魅力

eii的謊言與魅力 eii是實時企業的乙個重要部分,它可以讓我們獲得實際上不在資料倉儲裡的大量重要資訊。這樣我們就可以避免資料倉儲因不必要的資料而變得臃腫不堪。但eii不會淘汰資料倉儲,也不會取代它,而是補充和擴充套件資料倉儲!作為業界比較新的一項技術,企業資訊整合 enterprise infor...

誠實者與說謊者問題

問題描述 誠實者與說謊者 內容 有兩個人,乙個是誠實者,乙個是說謊者。誠實者只說真話,說謊者只說假話!兩個人都知道身後兩扇門哪個是對的,哪個是錯的!但情況是不知道誰是誠實者,誰是說謊者。要求 現在你只有一次機會向其中之一問乙個問題來確定那個對的門!你會怎麼問呢?答案 隨便找乙個人問 如果我問另外乙個...