編寫乙個最簡單的互動式題目

2021-05-10 08:30:30 字數 4048 閱讀 2958

最近無聊學著編了一下互動式型別的題目。平常網上互動式題目的庫檔案原始碼並不多見,在這裡把我寫的乙個題目分享給大家,希望對大家能夠有幫助。

題目是乙個經典問題,下面所引用的內容是全部的題目描述:

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個錯誤,不明所...