2020級cpp機考模擬題A卷-#題解1
為了各位朋友的身心健康(不是),我們按照題目難度順序來寫題解。
第一次寫題解,希望多點包容和鼓勵(恬不知恥
1:誰先輸出-4
題意:
輸入3個整數,按從大到小的順序輸出,每兩個數字間加一個空格。
題解:
輸入三個數,用一下排序(冒泡/選擇 排序法,或者 A?B:C),然後就可以輸出了。
上板子(氣泡排序法):
for (int i = 1;i < n;i++) { for (int j = 1;j <= n - i;j++) { if (t[j] > t[j + 1]) swap(t[j], t[j + 1]); } }
13:星號陣列-16
題意:
上下拼接正方形,同位置重合只顯示一條邊。
題解:
可以看做輸出b個,最後輸出一行的星號。
上板子(使用迴圈):
int main() { int a, b; cin >> a >> b; for (int i = 1;i <= b;i++) { for (int j = 1;j <= a-1;j++) { if (j == 1) { for (int p = 1;p <= a;p++) { cout<< "*"; } cout << endl; } else { for (int p = 1;p <= a;p++) { if (p == 1 || p == a)cout << "*"; else cout << " "; } cout<< endl; } } } for (int p = 1;p <= a;p++) { cout << "*"; } cout << endl; return 0; }
3:最大的乘積
題意:
找兩個數,使它們的乘積最大,然後輸出這個乘積。
題解:
依題意,本題給的資料不一定是正數,所以這邊建議找到最大的兩個數跟最小的兩個數,分別計算它們的乘積,輸出較大的那個。
使用迴圈找 最大/最小 的兩個數:
for (int i = 1;i < =2;i++)//因為只需要找兩個數,所以排序只需要兩次。 { for (int j = 1;j <= m - i;j++) { if (a[j] > a[j + 1])//要找最小的數的話,改成減號即可。 swap(a[j], a[j + 1]); } }//迴圈結束後,最後面的兩個數就是最大的兩個了,然後把它們相乘存一下。
這題沒有板子orz.
9:沉迷遊戲的大佬
題意:
給出經驗總值與各級所需經驗,求最終等級。
題解:
這題用迴圈解,每升一級把這一段所需要的經驗減去,注意到了滿級之後就不能升級了,所以在迴圈裡特判一下是否滿級。
上板子:
int n,x,d=1;//n為人物滿級等級,x為經驗總值,d為人物等級 cin >> n; int a[1000] = { 0 }; for(int i=1;i<n;i++) { cin >> a[i];//升級所需經驗 } cin >> x; int u = 1;//第幾級升級到第幾級 while (x >= a[u]&&d<n)//特判一下d是否<n,注意!不論你用for還是while,不能寫<=。 { x -= a[u]; d++; u++; } /*這裡如果用for,可寫為 for(;x >= a[u]&&d<n;d++) { x-=a[u]; u++; }*/ cout << d;
4:最長的妹紙序列
題意:
記錄字串中F最多連續個數。
題解:
錄入一個字串為男女生的佇列,用迴圈依次判斷字元是否為F,如果是則count++,如果不是就把count清零。
上板子(迴圈判斷部分):
for (int i = 0;i < s.length();i++) { if (s[i] == 'F')num++; else { if (num > n)n = num; num = 0; } }
7:石頭剪刀布
題意(開始應用題了,其實演算法實現上很簡單,然鵝你讀不懂題目 /滑稽):
兩個人石頭剪刀布,其中A開了天眼能預先知道蘇學長要出的是石頭、剪刀還是布。但是A出石頭、剪刀、布的次數有一個上限,石頭最多出a次,剪刀最多出b次,布最多出c次(可以選擇不出)。求A最多能贏幾局。
題解:
題目裡說了只需要求A最多贏幾句,所以不用管她會輸幾局,然後簡化題意之後這道題就會很簡單。
就只要在B出剪刀的時候A出石頭,所以A最多能贏的局數就只需要把A的石頭次數與B的剪刀次數比較,輸出較小值.....以此類推(剪刀跟布也用一樣的方法算)......
上板子(真的挺簡單的,建議自己看懂了做一遍):
string s; cin >> s; int a, b, c, o[4] = { 0 };// o 裡面儲存 b對應的剪刀、布、石頭的次數。 cin >> a >> b >> c; for (int i = 0;i < s.length();i++) { if (s[i] == 'j')o[1]++; else if (s[i] == 'b')o[2]++; else if (s[i] == 's')o[3]++; } int sum = 0; sum += min(o[1], a);// o[1] 代表的是剪刀, a 代表的是石頭,min(o[1],a) 就是A玩家用石頭最多能贏幾句。 sum += min(o[2], b); sum += min(o[3], c); cout << sum << endl;
8:MJ刷題目
題意:
程式設計競賽裡有n道題目,MJ做第i道題目需要花費t[i]時間。在統計競賽小分的時候,規定每道題目的小分是:從比賽開始時間到這道題目做出來經歷的時間,而MJ的小分將會是每道題的小分之和。假設MJ能夠在比賽結束前做出所有題目,並且可以任意調整做題順序。他想要讓自己的小分的值足夠小,問小分的最小值是多少?
題解:
很快你就能發現(不是),要小分的值最小,應該把用時短的題目先寫了。然後,聰明的你靈光一閃就又知道了,排序、迴圈後相加。
舉個栗子:
假如兩道題目,一道題目A用時2分鐘,一道題目B用時5分鐘。
依據題意,假如先做A,小分為2+(2+5)=9;假如先做B,小分為5+(5+2)=12。
由於每道題的用時裡都有前面的用時和,拿第一題舉例,這邊建議是把第一題的用時乘以題量,就是整個計算中第一題的時間了。對於上面的栗子,我們用這樣的方法就可以把它轉為:2*2+5*1=9;
上板子(其實主要看題解):
int time = 0; for (int i = 1;i <= n;i++)//個人習慣, 第一個數組裡我一般不存東西,所以從1開始迴圈。 { time += t[i] * (n-i+1); } cout << time;
10:毒蟲養成記
題意:
把毒蟲放進一個籠子裡,讓它們自相殘殺,最後存活的毒蟲就當成最厲害的毒蟲。由於毒蟲的毒性各有各的不同,即使很弱小的毒蟲也有機會幹掉很厲害的毒蟲。當A毒蟲幹掉B毒蟲以後,會把B毒蟲毒性的一半(如果這個值是小數,則保留其整數部分)加入到自己的毒性中,讓自己的毒性變得更強大。草原學姐把一堆毒蟲裝進了籠中,問最後倖存的毒蟲最大的毒性是多少?
題解:
雖然通過的人很多,但是由於我在這裡卡了一個小時,所以我把這題的位置往後放了。
依據題意,毒蟲A殺了B就可以得到它一半的毒性,且遇到小數時直接取整所以不必考慮毒性為奇數。那麼,假如A殺了B,A的毒性將表示為A+B/2。你很快就會發現(不是),由於自相殘殺過程中,每一個死去的毒蟲都會被浪費50%的毒性,而且這個毒性在後面可能還會被 /2 ,例如C殺了上面的A,那麼C的毒性為C+A/2+B/4(你看,B的毒性又被浪費了25%)。所以呢你很快就能得到一個重要結論:
讓毒性最強的蟲子去殺掉所有的蟲子
也就是說除了最強的那個蟲子保留原先的毒性,其餘 /2後加進去,這樣可以最小限度的浪費毒性。
具體操作:一次迴圈,找出最大值,其餘/2,然後再用一次迴圈,把除以二之後的加進去。
ps:不知道需不需要啊,我特判了m(蟲子數量)=1的情況。
上板子:
int m, a[120] = { 0 }; cin >> m; if (m == 1) { cin >> m; cout << m << endl; continue; } else { for (int i = 1;i <= m;i++) { cin >> a[i]; } int sum = 0; for (int j = 1;j < m;j++)//排序一次,找出最大值,放在a [m]的位置。 { if (a[j] > a[j + 1]) swap(a[j], a[j + 1]); } for (int i = 1;i < m;i++)//將除了最大的值以外都 /2。 { a[i] /= 2; } for (int j = 1;j <= m;j++)//把 /2 之後的毒蟲毒性存到最大的毒蟲裡。 { sum += a[j]; } cout << sum << endl; }
6:大規模殺傷性好人卡
題意:
有一個叫01的學長整天被妹紙發好人卡。妹紙丟出的好人卡具有範圍殺傷效果。離好人卡越遠傷害越小,傷害計算公式是:好人卡的傷害-距離,如果這個值為負的,那麼當成0,即沒有傷害。
有一天,01被妹紙們堵在一條長度為m的直線道路上,妹紙們對01發了很多張好人卡,每張好人卡具有各自的傷害值以及各自落下的位置。而01只能躲在整點的位置上(即0、1、2、...、m,一共m+1個候選位置),請你幫01找一個位置,讓01受到的總傷害最小。
題解:
每一張好人卡的造成的傷害=好人卡的傷害-距離。這裡要用到一個之前講過的函式:abs,使用時記得加上它的標頭檔案 #
具體操作:
把每張好人卡的傷害存在陣列a[ ]中,好人卡的位置存在陣列b[ ]中。然後來一波迴圈for(int i=0;i<=m;i++)來找到最小傷害mi;
上板子:
int m, p; cin >> m >> p; int a[502] = { 0 }, b[502] = { 0 }, c=0,mi=9999999;// mi 需要有一個初值,不然迴圈裡無法比較。 for (int i = 1;i <= p;i++) { cin >> a[i]; } for (int i = 1;i <= p;i++) { cin >> b[i]; } for (int j = 0;j <= m;j++) { for (int i = 1;i <= p;i++) { if (a[i] > abs(b[i] - j)) c += (a[i] - abs(b[i]-j));//c 用於記錄在 j 位置下受到的傷害的和。 } mi = min(c, mi); c = 0;//每次迴圈結束記得清零! } cout << mi << endl;
以上為#題解1的全部內容,後面的難題後面會另外再發一個。祝大家學習快樂!!