最近無聊學著編了一下互動式型別的題目。平常網上互動式題目的庫檔案原始碼並不多見,在這裡把我寫的乙個題目分享給大家,希望對大家能夠有幫助。
題目是乙個經典問題,下面所引用的內容是全部的題目描述:
problem : famous誰是名人
問題描述
matrix67所在的小鎮上有n(2<=n<=1000)個人,它們從1到n編號。在小鎮中,一些人認識另一些人,這種認識的關係是單向的。乙個人是名人當且僅當小鎮上所有的人都認識他,而除他之外的所有n-1個人他都不認識。假設這個小鎮上有且只有乙個名人,而你只能詢問諸如「a是否認識b」這樣的關係。請用不超過2000次的詢問找到這個名人。
互動方法
這個題目是乙個互動式的題目。我們不提供輸入檔案,同時也不需要任何輸出檔案。你需要呼叫乙個我們準備好的庫函式來完成所有的操作。你可以得到libfam.ppu和libfam.o兩個檔案。你需要把這兩個檔案放在和你的源程式相同的目錄下,並在源程式裡加入「uses libfam」完成對庫檔案的引用。我們的庫檔案提供了以下兩個函式和乙個過程:
function init:longint;
function know(a,b:longint):boolean;
procedure submit(sol:longint);
init函式只能呼叫一次。這個函式僅在程式開始時呼叫,他將返回n值,代表小鎮上的人數。
函式know(a,b)返回乙個布林值,它告知了編號為a的人與編號為b的人的關係。如果該函式返回true,則你獲得了「a認識b」這一資訊;如果該函式返回false,則你獲得了「a不認識b」這一資訊。該函式可以多次呼叫,每呼叫一次稱做為一次詢問。你的詢問次數不能超過2000次,也就是說,該函式最多被呼叫2000次。
submit過程只能呼叫一次。這個過程僅在程式結束時呼叫,用於提交你得到的答案,所帶的引數即是名人的編號。呼叫這個過程將終止你的程式,你可以在日誌檔案中看到反饋資訊。
乙個成功互動的例子
下面這一程式**說明了如何進行正確的操作。除了解釋如何使用互動庫之外,這個**不具有任何意義。它不具有提示你詢問方法的作用。
program famous;
uses libfam;
varn:longint;
foo,bar:boolean;
begin
n:=init; //初始化,得到n的值
foo:=know(1,3); //詢問1是否認識3
bar:=know(n-1,4); //詢問n-1是否認識4
submit(2); //所提交的答案為2
end.
你如何測試自己的程式
第一行:乙個整數n,代表人數;
第二行到第n+1行:輸入乙個01矩陣,數字與數字間用空格分隔。其中,第i行的第j個數字表示i是否認識j,「1」表示認識,「0」表示不認識。當i和j相等時,該位置上的0或1沒有意義。
乙個合法的test.in檔案內容可能如下: 3
1 1 0
0 0 0
1 1 1
容易看出,該輸入檔案表明n=3時的情況,其中第2個人是名人。
你的程式執行時將讀取該檔案的相關資訊並作為此次測試的資料。
程式退出後該目錄將生成乙個名為famous.log的檔案。該檔案是日誌檔案,它詳細記錄了你的程式與庫的互動過程。一些可能出現的情況如下(部分語句較長,用...省略):
init called more than once. 表明你的程式呼叫init函式超過1次。
file not exist. 表明目錄裡找不到test.in檔案或無法開啟該檔案。
error reading n. 讀入數字n時出錯。該位置可能有其它字元。
n must between 2 and 1000. test.in中輸入的n範圍不正確。n應該在2到1000之間。
error reading the matrix. 讀入01矩陣時出錯。該位置可能有其它字元。
numbers in matrix should... 矩陣中出現了除0和1以外的數字。
no famous person found... 你的輸入資料中沒有名人。
init called successfully. 程式呼叫init成功,繼續執行。
too many queries... 你的詢問次數超過2000次,程式被迫終止。
person # not exist. 你所詢問的人不存在。可能你的引數大於了n或小於1。
you asked a same person: #. 你的程式詢問了兩個相同的人的關係。
no.# : # # true/false 依次說明這是第幾次詢問、詢問的兩個編號和返回的結果。
submitted after # queries. 你的程式成功地提交了答案。同時你可以看到你的總詢問次數。
your answer: # 這是你提交的答案。
congrats, your answer... 你提交的答案是正確的。你的程式通過了這次測試。
oops, your answer is wrong...你提交的答案是錯誤的。同時你可以看到正確的答案是多少。
評分方法
當你提交的答案與我們的正確答案相符時得10分。我們一共將有10次測試,總共100分。
出現以下情況均不給分:
程式提交的答案錯誤或沒有提交答案;
程式執行時間超過1秒;
程式使用記憶體空間超過64m;
程式詢問次數超過2000次;
程式崩潰或意外退出;
錯誤訪問庫導致測試庫出錯;
程式訪問了其它外部檔案。
資料規模
對於30%的資料,n<=40;
對於50%的資料,n<=50;
對於70%的資料,n<=200;
對於100%的資料,n<=1000。
下面是乙個資料生成器。在實際測試中使用的資料檔名並不是「test.in」,防止選手直接讀入資料。因此,庫的**中讀入部分也要做相應的改動。資料未經過加密,因此這種方法不能徹底防止選手作弊。使用cena測試時,測試庫需要放在cena目錄的compilers/bin下。測試庫還需要一些其它的改動,比如log檔案可以改為只輸出該測試點是否得分的資訊(在cena中設定成用答案正確時應該輸出的log檔案與實際輸出的log檔案進行對比)。
const
c:array[0..9]of longint=
(2,30,40,47,50,172,200,532,797,1000);
vara:array[1..1000,1..1000]of longint;
i,j,k,n,t:longint;
begin
randseed:=13875;
for k:=0 to 9 do
begin
assign(output,'fam23z.'+chr(k+48)+'.in');
rewrite(output);
n:=c[k];
for i:=1 to n do
for j:=1 to n do a[i,j]:=random(2);
t:=random(n)+1;
for i:=1 to n do a[i,t]:=1;
for i:=1 to n do a[t,i]:=0;
writeln(n);
for i:=1 to n do
begin
for j:=1 to n do write(a[i,j],' ');
writeln;
end;
close(output);
end;
end.
乙個滿分程式的**可能如下:
uses libfam;
vari,t,n:integer;
begin
n:=init;
t:=1;
for i:=2 to n do if know(t,i) then t:=i;
submit(t);
end.
第乙個docker測試容器 互動式
第一步,run乙個容器並且進入互動介面 sudo docker run it name test ubuntu bin bash i 互動 t 偽tty 第二步,容器為了輕量化,並沒安裝vim 我們來裝乙個。apt get update apt get install vim 第三步,退出容器 同時...
Linux 實現簡單的互動式shell
實現簡單的互動式shell 使用已學習的各種c函式實現乙個簡單的互動式shell,要求 1 給出提示符,讓使用者輸入一行命令,識別程式名和引數並呼叫適當的exec函式執行程式,待執行完成後再次給出提示符。2 該程式可識別和處理以下符號 1 簡單的標準輸入輸出重定向 仿照例 父子程序ls wc l 先...
編寫乙個最簡單的osg遇到的坑
編寫乙個最簡單的osg遇到的坑 osg 的環境搭建好後,編寫乙個簡單的程式,如下 include include int main int argc,char ar 在工程的屬性面板上設定好,標頭檔案的路徑,鏈結庫和鏈結庫路徑。執行編譯,等待編譯結果,但過了一會兒懵逼了,出現了1144個錯誤,不明所...