1. 程式人生 > 實用技巧 >2020級cpp機考模擬題A卷-#題解1

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,使用時記得加上它的標頭檔案 #include<stdlib.h>,也就是abs(好人卡的位置-01學長的位置)。注意!表面上問的是你找個位置,最後輸出的卻是受到的最小傷害的值。

具體操作:

把每張好人卡的傷害存在陣列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的全部內容,後面的難題後面會另外再發一個。祝大家學習快樂!!