Ad Hoc类问题求解案例
Ad Hoc類問題
前言:在程序設計競賽的試題中,有這樣一類試題,解題不能套用現成的算法,也沒有模式化的求解方法,而是需要編程者自己設計算法來解答試題,這類試題被稱作Ad Hoc類試題,也被稱為雜題.
- 一方面,Ad Hoc類試題能夠比較綜合地反映編程者的智慧、知識基礎和創造性思維的能力;
- 另一方面,求解Ad Hoc類試題的自創的算法只針對某個問題本身,探索該問題的獨有性質,是一種專為解決某個特定的問題或完成某項特定的任務而設計的算法,因此Ad Hoc類試題的求解算法一般不具備普適意義和可推廣性。
求解Ad Hoc類問題的方法多樣,但按照數理分析和思維方式的角度,大致可分兩大類:
機理分析法實驗范例
Factstone Benchmark
試題來源:Waterloo local 2005.09.24
題目描述:
Amtel宣布,到2010年,它將開發出128位處理器的計算機;到2020年,它將開發出256位計算機;以此類推,Amtel實行每十年就將芯片字長長度翻一番的戰略。(在此前,Amtel于2000年開發了64位計算機;在1990年,開發了32位計算機;在1980年,開發了16位計算機;在1970年,開發了8位計算機;并首先在1960年開發了4位計算機。)
Amtel使用新的標準檢查等級——Factstone——來宣傳其新處理器的大大提高的能力。 Factstone等級被定義為這樣的最大整數n,使得n!可以表示為一個計算機的字的無符號整數(比如1960年的4位計算機可表示3!=6,而不能表示4!=24)。
輸入:
輸入給出若干測試用例。每個測試用例一行,給出年份y。在最后一個測
試用例后,在最后一行給出0。
輸出:
對于每個測試用例,輸出一行,給出Factstone等級。
示例:
Sample Input
1960 1981 0Sample Output
3 8題解分析:
采用順向思維方式去分析題目,給定一個年份 => 求解出處理器的字大小 k位=> 計算出最大的n使得n!成為一個符合字的大小2k?12^k-12k?1的無符號整數,即:
n!<2k?1n! < 2^k - 1 n!<2k?1
假定當年位 Y 年,則其處理器的字的位數為 K=22+?(Y?1960)/10?K=2^{2+\lfloor(Y-1960)/10\rfloor}K=22+?(Y?1960)/10?,得到K位二進制數的最大的無符號整數是2K?12^K-12K?1,則求n的方法有兩種:
算法實現:計算Y年字的位數K,累加log?2i\log_2ilog2?i,直到數字超過K為止,此時i-1即位Factstone等級。
#include<iostream> #include<bits/stdc++.h> #include<cmath> using namespace std; int main() {float Y;while(1){cin>>Y;if(Y == 0) break;unsigned long long K = pow(2,2+(unsigned long long)((Y-1960)/10));double i = 1;double n = log2(i);while(n <= K){n += log2(++i);}cout<<i-1<<endl;}getchar();return 0; }統計分析法實驗范例
當我們在一時得不到事物特征機理的情況下,我們可以先通過手算或者編程等方法測試得到一些數據,即問題的部分解,再利用數理統計知識對數據進行處理,從而得到最終的數學模型。
Ants
試題來源:Waterloo local 2004.09.19
題目描述:
一只螞蟻軍隊在長度為l厘米的橫竿上走,每只螞蟻的速度恒定,1cm/s。當一只行走的螞蟻到達橫桿終點的時候,它就立即掉了下去;當兩只螞蟻相遇的時候,他們就調轉頭,并開始往相反的方向走。我們知道螞蟻在橫桿上原來的位置,但是不知道螞蟻行走的方向。請您計算所有螞蟻從橫桿上掉下去的最早可能時間和最晚可能時間。
輸入:
輸入的第一行給出一個整數,表示測試用例個數。每個測試用例首先給出兩個整數:橫竿的長度(以厘米為單位)和在橫竿上的螞蟻的數量n。接下來給出n個整數,表示每只螞蟻在橫竿上從左端測量過來的位置,沒有特定的次序。所有輸入數據不大于1000000,數據間用空格分隔。
輸出:
對于輸入的每個測試用例,輸出用一個空格分隔的兩個數,第一個數是所有的螞蟻掉下橫竿的最早可能的時間(如果它們的行走方向選擇合適),第二個數是所有的螞蟻掉下橫竿的最晚可能的時間。
試題解析:
每只螞蟻都有2種爬行方向,那么1000000只螞蟻的爬行方式組合就達到了210000002^{1000000}21000000種,這是一個天文數字,因此不可能逐個枚舉螞蟻的爬行方式。
我們先研究螞蟻較少時的情況:
2只螞蟻的其中一個情況:
4只螞蟻的情況:
顯然,當螞蟻越來越多的時候,情況就越加復雜。而題解的瓶頸就是螞蟻相遇的情況。
假如出現這種情況:螞蟻永遠不會相遇,即所有的向左走的螞蟻都在向右走的螞蟻的左邊,那么很容易得出算法時間復雜度O(n)
讓我們再看下兩只螞蟻的例子,能否假設兩只螞蟻再相遇后,忽略對方,各自繼續朝著自己的方向走?如圖所示:
這就相當于忽略了相遇這一事件,也就是說可以假設這些螞蟻即使相遇了也不理采對方而是繼續走著自己的路。這樣,每只螞蟻掉落所用的時間就只有兩個取值:一個是向左右所用的時間,一個是向右走所用的時間。
由此得出,設
li為螞蟻i在橫桿上從左端過來測量的位置(1≤i≤n)l_i為螞蟻i在橫桿上從左端過來測量的位置(1\leq i\leq n) li?為螞蟻i在橫桿上從左端過來測量的位置(1≤i≤n)
設little和big為n只螞蟻掉下橫桿的最早和最晚可能時間,則
little=min1≤i≤n{li,L?li}little = {\underset { 1\leq i \leq n} {min} }\{l_i,L-l_i\} little=1≤i≤nmin?{li?,L?li?}
big=max1≤i≤n{li,L?li}big = {\underset { 1\leq i \leq n} {max} }\{l_i,L-l_i\} big=1≤i≤nmax?{li?,L?li?}
總結
以上是生活随笔為你收集整理的Ad Hoc类问题求解案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode 第 194 场周赛
- 下一篇: 艺赛旗开发技巧-根据文本点击网页元素