国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Vj程序設(shè)計復(fù)雜模擬題訓(xùn)練

這篇具有很好參考價值的文章主要介紹了Vj程序設(shè)計復(fù)雜模擬題訓(xùn)練。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1A?:?飛飛的賭神修煉手冊

飛飛很喜歡打牌,他決定苦練牌技,終成賭神!

飛飛有?A?×?B?張撲克牌。每張撲克牌有一個大小(整數(shù),記為 a,范圍區(qū)間是?0?到?A?-?1)和一個花色(整數(shù),記為 b,范圍區(qū)間是?0?到?B?-?1。

撲克牌是互異的,也就是獨一無二的,也就是說沒有兩張牌大小和花色都相同。

“一手牌”的意思是你手里有 5 張不同的牌,這 5 張牌沒有誰在前誰在后的順序之分,它們可以形成一個牌型。 我們定義了 9 種牌型,如下是 9 種牌型的規(guī)則,我們用“低序號優(yōu)先”來匹配牌型,即這“一手牌”從上到下滿足的第一個牌型規(guī)則就是它的“牌型編號”(一個整數(shù),屬于 1 到 9):

  1. 同花順: 同時滿足規(guī)則 5 和規(guī)則 4.
  2. 炸彈 : 5張牌其中有4張牌的大小相等.
  3. 三帶二 : 5張牌其中有3張牌的大小相等,且另外2張牌的大小也相等.
  4. 同花 : 5張牌都是相同花色的.
  5. 順子 : 5張牌的大小形如?x,?x?+?1,?x?+?2,?x?+?3,?x?+?4
  6. 三條: 5張牌其中有3張牌的大小相等.
  7. 兩對: 5張牌其中有2張牌的大小相等,且另外3張牌中2張牌的大小相等.
  8. 一對: 5張牌其中有2張牌的大小相等.
  9. 要不起: 這手牌不滿足上述的牌型中任意一個.

現(xiàn)在, 飛飛從?A?×?B?張撲克牌中拿走了 2 張牌!分別是?(a1,?b1)?和?(a2,?b2). (其中a表示大小,b表示花色)

現(xiàn)在要從剩下的撲克牌中再隨機拿出 3 張!組成一手牌??!

其實飛飛現(xiàn)在要預(yù)言他的未來的可能性,即他將拿到的“一手牌”的可能性,我們用一個 “牌型編號(一個整數(shù),屬于 1 到 9)” 來表示這手牌的牌型,那么他的未來有 9 種可能,但每種可能的方案數(shù)不一樣。

現(xiàn)在飛飛想要計算一下 9 種牌型中,每種牌型的方案數(shù)。

Input

第?1?行包含了整數(shù)?A?和?B?(1?≤?A?≤?25,?1?≤?B?≤?4).

第?2?行包含了整數(shù)?a1,?b1,?a2,?b2?(0?≤?a1,?a2?≤?A?-?1,?0?≤?b1,?b2?≤?B?-?1,?(a1,?b1)?≠?(a2,?b2)).

Output

輸出一行,這行有 9 個整數(shù),每個整數(shù)代表了 9 種牌型的方案數(shù)(按牌型編號從小到大的順序)

限制:設(shè)計程序進(jìn)行枚舉,不能使用數(shù)學(xué)公式推導(dǎo)出每種牌型的方案數(shù)式子!

限制:設(shè)計程序進(jìn)行枚舉,不能使用數(shù)學(xué)公式推導(dǎo)出每種牌型的方案數(shù)式子!

限制:設(shè)計程序進(jìn)行枚舉,不能使用數(shù)學(xué)公式推導(dǎo)出每種牌型的方案數(shù)式子!

測試樣例

樣例 1

輸入:

5 2
1 0 3 1

輸出:

0 0 0 0 8 0 12 36 0 

樣例 2

輸入:

25 4
0 0 24 3

輸出:

0 2 18 0 0 644 1656 36432 113344 

解答

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int A, B;
    cin >> A >> B;
    int a1, b1, a2, b2;
    cin >> a1 >> b1 >> a2 >> b2;
    int ff[9], f[9];
    for (int i = 0; i < 9; i++)
    {
        f[i] = 0;
        ff[i] = 0;
    }
    vector<pair<int, int>> s(5);
    pair<int, int> m, v;
    m.first = a1;
    v.first = a2;
    m.second = b1;
    v.second = b2;
    s[0] = m;
    s[1] = v;
    // s.push_back(m);
    // s.push_back(v);
    for (int i = 0; i < A; i++)
    {
        for (int j = 0; j < B; j++)
        {
            if (((i != s[0].first) || (j != s[0].second)) && (i != s[1].first || j != s[1].second))
            {
                pair<int, int> s1;
                s1.first = i;
                s1.second = j;
                s[2] = s1;
                for (int ii = 0; ii < A; ii++)
                {
                    for (int jj = 0; jj < B; jj++)
                    {
                        if ((ii != s[0].first || jj != s[0].second) && (ii != s[1].first || jj != s[1].second) && (ii != s[2].first || jj != s[2].second))
                        {
                            pair<int, int> ss;
                            ss.first = ii;
                            ss.second = jj;
                            // s.push_back(ss);
                            s[3] = ss;
                            for (int iii = 0; iii < A; iii++)
                            {
                                for (int jjj = 0; jjj < B; jjj++)
                                {
                                    if ((iii != s[0].first || jjj != s[0].second) && (iii != s[1].first || jjj != s[1].second) && (iii != s[2].first || jjj != s[2].second) && (iii != s[3].first || jjj != s[3].second))
                                    {
                                        pair<int, int> sss;
                                        sss.first = iii;
                                        sss.second = jjj;
                                        // s.push_back(sss);
                                        s[4] = sss;
                                        vector<pair<int, int>> aa(5);
                                        for (int k = 0; k < 5; k++)
                                        {
                                            aa[k] = s[k];
                                        }
                                        sort(aa.begin(), aa.end()); // 排序
                                        int h = 0;                  // 前后相減差1的個數(shù)
                                        int hh = 0;                 // 花色相同的個數(shù)
                                        int y = 0;                  // 三張牌相同的個數(shù)
                                        int yy = 0;                 // 前后數(shù)字相同的個數(shù)
                                        for (int i = 0; i < 4; i++)
                                        {
                                            if (aa[i].first == aa[i + 1].first - 1)
                                            {
                                                h++;
                                            }
                                            if (aa[i].second == aa[i + 1].second)
                                            {
                                                hh++;
                                            }
                                            if (i <= 2)
                                            {
                                                if (aa[i].first == aa[i + 2].first)
                                                {
                                                    y++;
                                                }
                                            }
                                            if (aa[i].first == aa[i + 1].first)
                                            {
                                                yy++;
                                            }
                                        }
                                        if (h == 4 && hh == 4) //同花順
                                        {
                                            f[0]++;
                                            ff[0] = 1;
                                        }
                                        else if (y == 2 && yy == 3) // 炸彈
                                        {
                                            f[1]++;
                                            ff[1] = 1;
                                        }
                                        else if (y == 1 && yy == 3) // 三帶二
                                        {
                                            f[2]++;
                                            ff[2] = 1;
                                        }
                                        else if (hh == 4 && h != 4) // 相同花色
                                        {
                                            f[3]++;
                                            ff[3] = 1;
                                        }
                                        else if (h == 4 && hh != 4) // 順子
                                        {
                                            f[4]++;
                                            ff[4] = 1;
                                        }
                                        else if (y == 1) //三張牌相同
                                        {
                                            f[5]++;
                                            ff[5] = 1;
                                        }
                                        else if (yy == 2) // 兩對
                                        {
                                            f[6]++;
                                            ff[6] = 1;
                                        }
                                        else if (yy == 1) // 一對
                                        {
                                            ff[7] = 1;
                                            f[7]++;
                                        }
                                        else
                                        {
                                            f[8]++;
                                        }
                                        // s.pop_back();
                                    }
                                }
                            }
                            // s.pop_back();
                        }
                    }
                }
                // s.pop_back();
            }
        }
    }
    for (int i = 0; i < 9; i++)
    {
        cout << f[i] / 6 << " ";
    }
    cout << endl;
    
    return 0;
}

2B :?TT與可憐的貓

題目描述

自從 TT 成為了助教,他就熱衷于給同學(xué)們解答疑問,于是他就沒有時間進(jìn)行陪他的貓貓玩了,真是一只可憐的小貓。

TT 在同一時間會與很多同學(xué)同時用 QQ(TT 特供版) 進(jìn)行答疑,有時 TT?開啟一個新的窗口,開始一個新的答疑對話;有時 TT?關(guān)閉一個窗口,結(jié)束一段答疑; 有時,為了及時回答著急的同學(xué),TT 會把一個對話窗口設(shè)置為置頂狀態(tài)(置頂狀態(tài)是一種虛擬的狀態(tài),窗口的實際位置并不會發(fā)生改變)。

你可以將 TT 的聊天窗口想象成一個隊列。如果現(xiàn)在沒有窗口處于置頂狀態(tài),那么在隊列中位列第一窗口視為在頂層,否則處于置頂狀態(tài)的窗口視為在頂層。請注意,不可能同時存在兩個窗口處于置頂狀態(tài)(也就是說,處于置頂狀態(tài)的窗口,要么不存在,要么只有一個)。如果當(dāng)前置頂的窗口被關(guān)閉了,則剩余隊列中第一窗口視為在頂層。

TT 為了安撫自己的貓,于是給貓貓看自己的聊天記錄解悶,根據(jù)貓貓看屏幕中窗口的時間,TT 給每個窗口分配了一個喜愛度,TT 認(rèn)為喜愛度越高,貓貓越開心。由于貓貓具有不確定的生物特性,所以所有的喜愛度都是不同的。

作為 TT 特供版 QQ 的研發(fā)人員,你要負(fù)責(zé)完成的工作是為軟件記錄 TT 的操作,形成一個日志系統(tǒng)。日志有固定的記錄格式:OpId #X: MSG.?,其中?X?是操作的編號,而?MSG?是日志的提示信息,需要使用特定的字符串進(jìn)行替換。

TT 可能會用到的操作如下:

  1. Add u:?TT 打開一個喜愛度為?u?的新窗口,若?u?不與當(dāng)前窗口隊列中的某個窗口重復(fù),則該新窗口將新建成功,并成為窗口隊列中的最后一個窗口。 如果創(chuàng)建成功,則?MSG?記錄?success。 否則,?MSG?記錄?same likeness 。

  2. Close u:?TT 關(guān)掉了一個喜愛度為?u?的窗口,如果該窗口存在,則將其關(guān)閉,MSG?記錄?close u with c,u?表示喜愛度,c?表示該窗口上次打開至今交流的話的數(shù)量。若該窗口不存在,則?MSG?記錄?invalid likeness。

  3. Chat w:?TT 和頂層窗口交流了?w?句話,如果當(dāng)前隊列中沒有窗口,則?MSG?記錄?empty,否則記錄?success。

  4. Rotate x:?將隊列中第?x?個窗口放在隊首,若?x?大于當(dāng)前隊列中窗口數(shù)或小于?1?,則?MSG?記錄?out of range,否則記錄?success。舉個例子,目前隊列中有喜愛度為 5,3,2,8 的四個窗口,Rotate 3 之后,會將喜愛度為 2 的第 3 個窗口放在首位,結(jié)果為 2,5,3,8。

  5. Prior:?TT 將目前喜愛度最大的窗口放在隊首,如果當(dāng)前隊列中沒有窗口,則?MSG?記錄?empty,否則記錄?success

  6. Choose u:?TT 將喜愛度為?u?的窗口放在隊首,如果喜愛度為?u?的窗口存在,則?MSG?記錄?success,否則記錄?invalid likeness。

  7. Top u:?TT 將喜愛度為?u?的窗口設(shè)定為置頂狀態(tài),如果喜愛度為?u?的窗口存在,則?MSG?記錄?success,否則記錄?invalid likeness。注意,處于置頂狀態(tài)的窗口最多不超過一個,也就是說,如果在此次設(shè)定前已經(jīng)有處于置頂狀態(tài)的窗口,則原有置頂狀態(tài)的窗口的置頂狀態(tài)將會消失。(置頂只是一種虛擬的狀態(tài),原窗口在隊列中的位置不會發(fā)生變化)

  8. Untop:?TT 取消當(dāng)前處于置頂狀態(tài)窗口的置頂狀態(tài)。如果當(dāng)前沒有窗口處于置頂狀態(tài),則?MSG?記錄?no such person,否則記錄?success。

最后,由于 TT 要給自己的貓貓樹立一個講文明有禮貌的榜樣,所以在上述操作完成后,還要進(jìn)行若干次操作,這些操作是:與當(dāng)前隊列中所有說過話的窗口說拜拜。MSG?記錄?Bye u: c,?u?表示喜愛度,c?表示該窗口上次打開至今交流的話的數(shù)量。即:TT 先和位于頂層的窗口說拜拜,然后將其關(guān)閉,如果 TT 沒有和當(dāng)前頂層窗口說過話,則直接將其關(guān)閉,如此操作下去,直到隊列為空。

輸入描述

第一行包含一個整數(shù)?T(T≤5),表示數(shù)據(jù)組數(shù)。

對于每組數(shù)據(jù),第一行一個?n,表示執(zhí)行的操作數(shù),其中?0<n≤5000。接下來?n?行,每行輸入一個操作,保證所有輸入數(shù)據(jù)中的整數(shù)不大于?109。

輸出描述

對于每個指定的操作,按照日志的格式,每個操作行。對于最后的非指定操作,同樣按照日志的格式,每個操作一行。

測試樣例

樣例 1

輸入:

1
30
Add 4
Add 3
Chat 4
Add 3
Rotate 2
Chat 5
Prior
Top 3
Choose 4
Rotate 1
Add 2
Close 4
Chat 7
Choose 2
Chat 7
Add 3
Top 2
Add 4
Choose 3
Chat 7
Prior
Top 3
Rotate 1
Rotate 3
Chat 7
Top 4
Add 2
Close 2
Prior
Add 4

輸出:

OpId #1: success.
OpId #2: success.
OpId #3: success.
OpId #4: same likeness.
OpId #5: success.
OpId #6: success.
OpId #7: success.
OpId #8: success.
OpId #9: success.
OpId #10: success.
OpId #11: success.
OpId #12: close 4 with 4.
OpId #13: success.
OpId #14: success.
OpId #15: success.
OpId #16: same likeness.
OpId #17: success.
OpId #18: success.
OpId #19: success.
OpId #20: success.
OpId #21: success.
OpId #22: success.
OpId #23: success.
OpId #24: success.
OpId #25: success.
OpId #26: success.
OpId #27: same likeness.
OpId #28: close 2 with 7.
OpId #29: success.
OpId #30: same likeness.
OpId #31: Bye 3: 26.

解答

#include <bits/stdc++.h>

using namespace std;
// #define inf 1e6
long long T;
long long n;
long long tot;

struct Window
{
    long long x, y; // y為說話量,x為喜歡程度,z為是否打開
    /* data */
} w[1000000];
long long top; // 置頂?shù)拇翱诘男蛱?string a;
long long b;
// pair<long long, long long> C[1000000]; // first為喜愛度,second為是否打開
// 初始化
void init()
{
    for (long long i = 0; i < 1000000; i++)
    {
        // C[i].first = -1;
        // C[i].second = 0;
        w[i].x = -1;
        w[i].y = 0;
        // w[i].z = 0;
        // w[i].k = 0;
    }
    // w[1]. = 1;
    tot = 1;
}
long long j;
void play(long long i);

void bye();
int main()
{
    // freopen("1.txt", "r", stdin);
    // freopen("2.txt", "w", stdout);
    cin >> T;

    for (long long i = 1; i <= T; i++)
    {
        cin >> n;
        init();
        top = -1;
        for (j = 1; j <= n; j++)
        {
            cin >> a;
            play(j);
        }
        bye();
    }
    // system("pause");
    return 0;
}

void bye()
{
    if (top != -1)
    {
        if (w[top].y != 0)
        {
            // j++;
            cout << "OpId #" << j << ": ";
            cout << "Bye " << w[top].x << ": " << w[top].y << "." << endl;
            j++;
        }
        // }
        for (long long i = 1; i < tot; i++)
        {
            if (w[i].x == w[top].x || w[i].y == 0)
            {
                continue;
            }
            else
            {
                // j++;
                cout << "OpId #" << j << ": ";
                cout << "Bye " << w[i].x << ": " << w[i].y << "." << endl;
                j++;
            }
        }
    }
    else
    {
        for (long long i = 1; i < tot; i++)
        {
            if (w[i].y != 0)
            {
                cout << "OpId #" << j << ": ";
                cout << "Bye " << w[i].x << ": " << w[i].y << "." << endl;
                j++;
            }
        }
    }
}

void play(long long i)
{
    // switch (a)
    // {
    if (a == "Add")
    {
        cin >> b;
        long long g = 1;
        for (; g < tot; g++)
        {
            if (w[g].x == b)
            {
                break;
            }
        }
        // long long d = 1;
        // for (; d < tot; d++)
        // {
        //     if (C[d].first == b)
        //     {
        //         break;
        //     }
        // }
        if (g >= tot)
        {
            w[tot].x = b;
            // C[tot] = 1;
            tot++;

            cout << "OpId #" << i << ": success." << endl;
        }
        // else if (C[d].second == 0)
        // {
        // cout << "OpId #" << i << ": success." << endl;
        // }
        else
        {
            cout << "OpId #" << i << ": same likeness." << endl;
        }
        // C[tot - 1] = 1;
        // C[tot - 1].first = b;
        // C[tot - 1].second = 1;
        // break;
    }
    else if (a == "Close")
    {
        cin >> b;
        long long g = 1;
        for (; g < tot; g++)
        {
            if (w[g].x == b)
            {
                break;
            }
        }
        if (g >= tot)
        {
            cout << "OpId #" << i << ": invalid likeness." << endl;
        }
        else
        {
            if (top > g && top != -1)
            {
                top--;
            }
            else if (top == g)
            {
                top = -1;
            }
            cout << "OpId #" << i << ": close " << b << " with " << w[g].y << "." << endl;
            for (int h = g; h < tot - 1; h++)
            {
                w[h].x = w[h + 1].x, w[h].y = w[h + 1].y;
            }
            w[tot - 1].x = -1, w[tot - 1].y = 0;
            tot--;
            // long long d = 1;
            // for (; d < tot; d++)
            // {
            //     if (C[d].first == b)
            //     {
            //         break;
            //     }
            // }
            // if (C[d].second != 0)
            // {
            // C[d].second = 0;
            // w[g].z = 0;

            // w[g].y = 0;
            // }
            // else
            // {
            //     cout << "OpId #" << i << ": invalid likeness." << endl;
            // }
        }
        // break;
    }
    else if (a == "Chat")
    // case "Chat":
    {
        cin >> b;
        if (tot == 1)
        {
            cout << "OpId #" << i << ": empty." << endl;
        }
        else
        {
            if (top == -1)
            {
                w[1].y = b + w[1].y;
                // C[1].second = 1;
                cout << "OpId #" << i << ": success." << endl;
            }
            else
            {
                // if (C[top].second == 0)
                // {
                //     w[1].y = b;
                //     C[1] = 1;
                cout << "OpId #" << i << ": success." << endl;
                // }
                // else
                // {
                w[top].y = b + w[top].y;
                // C[top] = 1;
                // }
            }
        }
    }
    else if (a == "Rotate")
    // case "Rotate":
    {
        cin >> b;
        if (b >= tot || b < 1)
        {
            cout << "OpId #" << i << ": out of range." << endl;
        }
        else
        {
            if (top < b && top != -1)
            {
                top++;
            }
            else if (top == b)
            {
                top = 1;
            }
            long long x1, y1, z1;
            x1 = w[b].x, y1 = w[b].y;
            for (long long g = b; g > 1; g--)
            {
                w[g].x = w[g - 1].x;
                w[g].y = w[g - 1].y;
                // w[g].z = w[g - 1].z;
            }
            w[1].x = x1, w[1].y = y1;
            cout << "OpId #" << i << ": success." << endl;
        }
        // break;
    }
    else if (a == "Prior")
    // case "Prior":
    {
        if (tot == 1)
        {
            cout << "OpId #" << i << ": empty." << endl;
        }
        else
        {
            cout << "OpId #" << i << ": success." << endl;
            long long f = 1;
            long long u = w[1].x;
            for (long long g = 1; g < tot; g++)
            {
                if (w[g].x > u)
                {
                    u = w[g].x;
                    f = g;
                }
            }
            if (top < f && top != -1)
            {
                top++;
            }
            else if (top == f)
            {
                top = 1;
            }
            long long x1, y1, z1;
            x1 = w[f].x, y1 = w[f].y;
            for (long long g = f; g > 1; g--)
            {
                w[g].x = w[g - 1].x;
                w[g].y = w[g - 1].y;
                // w[g].z = w[g - 1].z;
            }
            w[1].x = x1, w[1].y = y1;
        }
        // break;
    }
    else if (a == "Choose")
    // case "Choose":
    {
        cin >> b;
        long long g = 1, f = -1;
        for (; g < tot; g++)
        {
            if (w[g].x == b)
            {
                f = g;
                break;
            }
        }
        if (f < tot && f != -1)
        {
            long long x1, y1, z1;
            if (top < f && top != -1)
            {
                top++;
            }
            else if (top == f)
            {
                top = 1;
            }
            x1 = w[f].x, y1 = w[f].y;
            for (long long h = f; h > 1; h--)
            {
                w[h].x = w[h - 1].x;
                w[h].y = w[h - 1].y;
            }
            w[1].x = x1, w[1].y = y1;
            cout << "OpId #" << i << ": success." << endl;
        }
        else
        {
            cout << "OpId #" << i << ": invalid likeness." << endl;
        }
        // break;
    }
    else if (a == "Top")
    // case "Top":
    {
        cin >> b;
        long long g = 1, f = -1;
        for (; g < tot; g++)
        {
            if (w[g].x == b)
            {
                f = g;
                break;
            }
        }
        if (f < tot && f != -1)
        {
            top = f;
            cout << "OpId #" << i << ": success." << endl;
        }
        else
        {
            cout << "OpId #" << i << ": invalid likeness." << endl;
        }
        // break;
    }
    else if (a == "Untop")
    // case "Untop":
    {
        // long long g = 1;
        // for (; g < tot; g++)
        // {
        //     // if (w[g].k == 2)
        //     // {
        //     //     break;
        //     // }
        // }
        if (top != -1)
        {
            top = -1;
            cout << "OpId #" << i << ": success." << endl;
        }
        else
        {
            cout << "OpId #" << i << ": no such person." << endl;
        }
        // break;
    }
    // }
}

3C :?記事本

注:本題有較多的部分分,請參看數(shù)據(jù)規(guī)模部分。

題目描述

記事本是 Windows 平臺下一款經(jīng)典的文本編輯器,其存儲文件的擴展名為?.txt,文件屬性沒有任何格式標(biāo)簽或者風(fēng)格,所以相當(dāng)適合在 DOS 環(huán)境中編輯。

在本題中,可能會用到的按鍵如下圖所示:

光標(biāo)移動

光標(biāo)表示當(dāng)前要進(jìn)行輸入等操作的位置,在本題中,我們假設(shè)所有字符都是等寬的。

光標(biāo)的位置可以用行列坐標(biāo)來描述,光標(biāo)所在的行和列均從 1 開始,例如:

以下操作可以進(jìn)行光標(biāo)的移動,使用?MOVE <comd>?輸入相關(guān)的操作,其中?<comd>?表示指令,可以使用以下字符串代替:

  • Home:把光標(biāo)移動到當(dāng)前行的開頭。
  • End:把光標(biāo)移動到當(dāng)前行的末尾。
  • Up:光標(biāo)移動到上一行的相同列。
    • 若當(dāng)前為第一行,則不進(jìn)行任何操作。
    • 若上一行的列數(shù)小于當(dāng)前光標(biāo)的列數(shù),則將光標(biāo)移動到上一行的末尾。
  • Down:光標(biāo)移動到下一行的相同列。
    • 若當(dāng)前為最后一行,則不進(jìn)行任何操作。
    • 若下一行的列數(shù)小于當(dāng)前光標(biāo)的列數(shù),則將光標(biāo)移動到下一行的末尾。
  • Left:光標(biāo)左移一位。
    • 若當(dāng)前光標(biāo)位于記事本開始,則不進(jìn)行任何操作。
    • 若當(dāng)前光標(biāo)處于某一行的開頭,則將光標(biāo)移動到上一行的末尾。
  • Right:光標(biāo)右移一位。
    • 若當(dāng)前光標(biāo)位于記事本末尾,則不進(jìn)行任何操作。
    • 若當(dāng)前光標(biāo)處于某一行的末尾,則將光標(biāo)移動到下一行的開頭。

輸入

以下操作可以在光標(biāo)后進(jìn)行輸入,使用?INSERT <comd>?輸入相關(guān)的操作,其中?<comd>?表示指令,可以使用以下字符串代替:

  • Char <char>:輸入一個字符,其中?<char>?是輸入的字符。

    • <char>?可能是一下字符中的任意一個:

    注:下列字符中不包含空格與換行符。

    `1234567890-=~!@#$%^&*()_+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:"zxcvbnm,./ZXCVBNM<>?
    
    • 例如:INSERT Char a?表示在當(dāng)前光標(biāo)后插入?a?字符。
  • Enter:輸入換行符,并進(jìn)行換行。

  • Space:輸入空格。

  • Paste:在當(dāng)前光標(biāo)后,插入粘貼板中的內(nèi)容,若粘貼板中無內(nèi)容,則忽略當(dāng)前操作。

刪除

以下操作可以刪除記事本中的內(nèi)容,使用?REMOVE <comd>?輸入相關(guān)的操作,其中?<comd>?表示指令,可以使用以下字符串代替:

  • Del:刪除當(dāng)前光標(biāo)位置之后的一個字符。
    • 若該字符為換行符,則當(dāng)前行與下一行合并為一行。
    • 若當(dāng)前光標(biāo)在文件末尾,則忽略當(dāng)前操作。
  • Backspace:刪除當(dāng)前光標(biāo)位置之前的一個字符。
    • 若該字符為換行符,則當(dāng)前行與上一行合并為一行。
    • 若當(dāng)前光標(biāo)在文件開頭,則忽略當(dāng)前操作。

粘滯功能(分?jǐn)?shù)占比 24 分)

輸入?SHIFT?指令,可以啟動或關(guān)閉粘滯功能。

  • 開始時粘滯功能默認(rèn)為關(guān)閉狀態(tài),之后每次點擊:

    • 若當(dāng)前為啟動狀態(tài),則關(guān)閉;
    • 若當(dāng)前為關(guān)閉狀態(tài),則啟動。
  • 粘滯功能啟動時,記錄當(dāng)前的光標(biāo)位置為?記錄點。

  • 粘滯功能關(guān)閉時,若此時的光標(biāo)位置與?記錄點?的位置不同,則進(jìn)入選中狀態(tài)。

  • 粘滯功能啟動后,直到功能關(guān)閉前,不會對記事本進(jìn)行除光標(biāo)移動外的任何操作。

當(dāng)進(jìn)入選中狀態(tài)后,通過記錄點與當(dāng)前光標(biāo),可以唯一的確定一段內(nèi)容,現(xiàn)令記錄點與光標(biāo)之間的所有字符(包括換行符)為?選中字段。

例如,記錄點位于第 1 行第 2 列,光標(biāo)位于第 2 行第 4 列時,選中字段如下圖所示:

當(dāng)前?處于選中狀態(tài)?時,對于不同的情況,需要按照序號依次執(zhí)行以下操作:

  • 若進(jìn)行光標(biāo)移動

    1. 退出選中狀態(tài);
    2. 嘗試進(jìn)行光標(biāo)的移動(無論光標(biāo)最終是否移動,都會退出選中狀態(tài))。
  • 若進(jìn)行輸入

    1. 將選中內(nèi)容替換為輸入內(nèi)容;
    2. 退出選中狀態(tài)
  • 若進(jìn)行刪除

    1. 刪除當(dāng)前選中內(nèi)容;
    2. 退出選中狀態(tài)。
  • 若再次啟動粘滯功能退出選中狀態(tài),但保留上一次選中字段的?記錄點?作為當(dāng)前記錄點

  • 若進(jìn)行查找,字?jǐn)?shù)統(tǒng)計,復(fù)制,打印操作,則在操作后仍然保持選中狀態(tài)

查找

輸入?FIND <word>?指令,進(jìn)行字符串查找,其中?<word>?為輸入的要查找的字符串,該字符串中不包含空格與換行符。

執(zhí)行該指令時,要根據(jù)當(dāng)前是否處于選中狀態(tài)做不同的處理:

  • 若當(dāng)前處于選中狀態(tài):查找輸入字符串在選中字段中的出現(xiàn)次數(shù)并輸出。
  • 否則:查找輸入字符串在當(dāng)前記事本中的出現(xiàn)次數(shù)并輸出。

例如:當(dāng)前沒有選中的內(nèi)容,且記事本中的內(nèi)容為?ababa,若執(zhí)行?FIND aba,則應(yīng)當(dāng)輸出 2,分別在第 1 列與第 3 列出現(xiàn)過。

字?jǐn)?shù)統(tǒng)計

輸入?COUNT?指令,進(jìn)行字?jǐn)?shù)統(tǒng)計。

執(zhí)行該指令時,要根據(jù)當(dāng)前是否處于選中狀態(tài)做不同的處理:

  • 若當(dāng)前處于選中狀態(tài):輸出當(dāng)前選中字段中的可見字符(不包括空格與換行符)的數(shù)量。
  • 否則:輸出當(dāng)前文檔中可見字符(不包括空格與換行符)的數(shù)量。

復(fù)制

輸入?COPY?指令,進(jìn)行復(fù)制操作。

執(zhí)行該指令時,要根據(jù)當(dāng)前是否處于選中狀態(tài)做不同的處理:

  • 若當(dāng)前處于選中狀態(tài):復(fù)制選中字段到粘貼板;
  • 否則,
    • 若當(dāng)前行不為空:復(fù)制當(dāng)前行的內(nèi)容(不包括換行符)到粘貼板;
    • 否則:忽略當(dāng)前操作。

打印

輸入?PRINT?指令,輸出當(dāng)前的記事本中的全部內(nèi)容,并在之后輸出一個換行符。

輸入格式

輸入包含?n+1?行。
第一行包含一個整數(shù)?n,表示接下來指令的數(shù)量。
接下來?n?行,每行一條指令,格式形如題目描述中的敘述。

輸出格式

對于需要輸出的指令,進(jìn)行相應(yīng)的輸出。
若為?FIND?與?COUNT?操作,輸出一行表示相應(yīng)的數(shù)字。
若為?PRINT?操作,則輸出若干行,表示記事本的當(dāng)前內(nèi)容,并在之后輸出一個換行。

請注意:所有的輸出不要有多余的空格。

測試樣例

樣例輸入

20
INSERT Char #
INSERT Enter
INSERT Char C
INSERT Enter
INSERT Space
INSERT Char _
INSERT Char _
PRINT
INSERT Char >
INSERT Enter
INSERT Char h
INSERT Char h
INSERT Char h
INSERT Enter
PRINT
COUNT
FIND __
REMOVE Del
REMOVE Backspace
PRINT

樣例輸出

#
C
 __
#
C
 __>
hhh

8
1
#
C
 __>
hhh

數(shù)據(jù)規(guī)模

對于?100%?的測試數(shù)據(jù),1≤n≤5000。

不同測試點所包含的功能不同,其具體情況如下表所示。

解答

#include <bits/stdc++.h>
using namespace std;
const string NULLSTR = "null";
const string ENTER = "\n";
const string SPACE = " ";
vector<string> line;     //lines of the file
vector<string> pasteBin; //lines of pasteBin
vector<string> selBin;   //lines of selection
struct pos
{
    int row = 1, col = 1;
    bool operator<(const pos &pp) const
    {
        if (row == pp.row)
            return col < pp.col;
        return row < pp.row;
    }
    bool operator==(const pos &pp) const
    {
        return (row == pp.row) && (col == pp.col);
    }
    pos(int r, int c) : row(r), col(c) {}
    pos() { row = col = 1; }
};
pos Cursor;      //position of the Cursor 0=row,1=column,element=1,2,...
bool shifted = false;     //shift enabled or not.
bool inSelection = false; //selection mode enabled or not.
pos remPoint;             //remPoint for selection. (Just a copy of the Cursor there.)
pos selection[2];         //selection area.
int getSpeciLineIndex(const pos &p) { return p.row - 1; }
int getSpeciCharIndex(const pos &p) { return p.col - 2; }
int getSpeciLineFullLength(const pos &p) { return line[getSpeciLineIndex(p)].length(); } //get the string length of current line.
int getSpeciLineVisLength(const pos &p)
{
    if (*(line[getSpeciLineIndex(p)].rbegin()) == '\n')
        return line[getSpeciLineIndex(p)].length() - 1;
    return getSpeciLineFullLength(p);
}
string getSpeciCursorLeftSub(const pos &p) { return line[getSpeciLineIndex(p)].substr(0, p.col - 1); } //get the substring on the left of the Cursor of the line.
string getSpeciCursorRightSub(const pos &p) { return line[getSpeciLineIndex(p)].substr(p.col - 1); }   //get the substring on the right of the Cursor of the line.
string getSpeciLineVisStr(const pos &p) { return line[getSpeciLineIndex(p)].substr(0, getSpeciLineVisLength(p)); }
void theCopy(vector<string> &);
vector<string> getSelectionArea()
{ //return the range of selection. if not in selection, then  return the whole file.
    vector<string> range;
    if (inSelection)
    {
        //        pasteBinBackUp=pasteBin;
        theCopy(selBin);
        range = selBin;
        //        pasteBin=pasteBinBackUp;
    }
    else
        range = line;
    return range;
}
void Move(int type)
{
    inSelection = false;
    bool moveLR = false;
    if(type == 1){
        Cursor.col = 1;
    }else if(type == 2){
        Cursor.col = getSpeciLineVisLength(Cursor) + 1;
    }else if(type==3){
        if (Cursor.row == 1)
                return;
            moveLR = false;
            if (getSpeciLineVisLength(pos(Cursor.row - 1, Cursor.col)) < Cursor.col - 1)
                moveLR = true; //moded getCurLineLength().
            --Cursor.row;
            if (moveLR)
                Move(2);
    }else if(type ==4){
        if (Cursor.row == line.size())
                return;
            moveLR = false;
            if (getSpeciLineVisLength(pos(Cursor.row + 1, Cursor.col)) < Cursor.col - 1)
                moveLR = true; //moded getCurLineLength().
            ++Cursor.row;
            if (moveLR)
                Move(2);
    }else if(type==5){
        if (Cursor.row == 1 && Cursor.col == 1)
                return;
            if (Cursor.col == 1)
            {
                Move(3);
                Move(2);
                return;
            }
            --Cursor.col;
    }else if(type ==6){
        if (Cursor.row == line.size() && Cursor.col == getSpeciLineVisLength(Cursor) + 1)
                return;
            if (Cursor.col == getSpeciLineVisLength(Cursor) + 1)
            { //moded getCurLineLength().
                Move(4);
                Move(1);
                return;
            }
            ++Cursor.col;
    }else if(type ==7){
        Cursor.col = getSpeciLineVisLength(Cursor) + 2; //moded getCurLineLength().
    }

    
}

void insert(int, string arg);
void createNextLineWithStr(string str)
{
    auto ins = line.begin();
    for (int i = 1; i <= getSpeciLineIndex(Cursor); i++)
        ++ins;
    line.insert(++ins, str);
    Move(4);
    Move(2);
}

void theCopy(vector<string> &bin)
{
    if (inSelection)
    {
        bin.clear();
        if (selection[0].row == selection[1].row)
        {
            int leftIndex = getSpeciCharIndex(selection[0]) + 1;
            int rightIndex = getSpeciCharIndex(selection[1]);
            if (leftIndex >= 0 && rightIndex >= 0)
                bin.push_back(line[getSpeciLineIndex(selection[1])].substr(leftIndex, rightIndex - leftIndex + 1));
        }
        else
        {
            int upCharIndex = getSpeciCharIndex(selection[0]) + 1;
            int upLineIndex = getSpeciLineIndex(selection[0]);
            int dnCharIndex = getSpeciCharIndex(selection[1]);
            int dnLineIndex = getSpeciLineIndex(selection[1]);
            if (upCharIndex >= 0)
                bin.push_back(line[upLineIndex].substr(upCharIndex));
            else
                bin.push_back(line[upLineIndex]);
            for (int i = upLineIndex + 1; i < dnLineIndex; i++)
            {
                string tmp = line[i];
                bin.push_back(tmp);
            }
            if (dnCharIndex >= 0)
                bin.push_back(line[dnLineIndex].substr(0, dnCharIndex + 1));
        }
        return;
    }
    else if (getSpeciLineVisLength(Cursor) != 0)
    {
        bin.clear();
        bin.push_back(getSpeciLineVisStr(Cursor));
        return;
    }
}

void theRemove(int);
void insert(int type, string arg)
{
    vector<string>::iterator ins;
    string left, right;
    if (inSelection)
    {
        if (type == 4 && pasteBin.empty())
            return;
        if (selection[1] == selection[0])
        {
            Cursor = selection[1];
            inSelection = false;
            insert(type, arg);
            return;
        }
        theRemove(1); //type can be any value.
        insert(type, arg);
        inSelection = false;
        return;
    }
    switch (type)
    {
        case 1:
            line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + arg + getSpeciCursorRightSub(Cursor);
            Cursor.col += arg.length();
            break;
        case 2:
            right = getSpeciCursorRightSub(Cursor);
            line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + ENTER;
            ins = line.begin();
            for (int i = 1; i <= getSpeciLineIndex(Cursor); i++)
                ++ins;
            line.insert(++ins, right);
            Move(4);
            Move(1);
            break;
        case 3:
            line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + SPACE + getSpeciCursorRightSub(Cursor);
            ++Cursor.col;
            break;
        case 4:
            if (pasteBin.empty())
                return;
            right = getSpeciCursorRightSub(Cursor);
            if (pasteBin.size() == 1 && *(pasteBin[0].rbegin()) != '\n')
            {
                line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + pasteBin[0] + right;
                for (int i = 0; i < pasteBin[0].size(); i++)
                    Move(6);
            }
            else
            {
                int curLine = -1;
                line[getSpeciLineIndex(Cursor)] = getSpeciCursorLeftSub(Cursor) + pasteBin[++curLine];
                for (int i = 1; i < pasteBin.size() - 1; i++)
                    createNextLineWithStr(pasteBin[++curLine]);
                if (*(pasteBin[pasteBin.size() - 1].rbegin()) != '\n')
                {
                    if (curLine + 1 <= pasteBin.size() - 1)
                        createNextLineWithStr(pasteBin[pasteBin.size() - 1] + right);
                    Move(1);
                    for (int i = 0; i < pasteBin[pasteBin.size() - 1].size(); i++)
                        Move(6);
                }
                else
                {
                    if (curLine + 1 <= pasteBin.size() - 1)
                        createNextLineWithStr(pasteBin[pasteBin.size() - 1]);
                    createNextLineWithStr(right);
                    Move(1);
                }
            }
            break;
    }
}

void theRemove(int type)
{
    vector<string>::iterator ins;
    string left, right;
    if (inSelection)
    {
        theCopy(selBin);
        left = getSpeciCursorLeftSub(selection[0]);
        right = getSpeciCursorRightSub(selection[1]);
        Cursor = selection[0];
        line[getSpeciLineIndex(selection[0])] = left + right;
        int firstDelLineIndex;
        firstDelLineIndex = getSpeciLineIndex(selection[0]) + 1;
        for (int i = firstDelLineIndex; i <= selection[1].row - 1;)
        {
            ins = line.begin();
            for (int j = 1; j <= i; j++)
                ++ins;
            line.erase(ins);
            --selection[1].row;
        }
        inSelection = false;
        if (Cursor.row > line.size())
        {
            Move(3);
            Move(2);
        }
        return;
    }
    switch (type)
    {
        case 1:
            if (getSpeciLineIndex(Cursor) + 1 == line.size() && getSpeciCharIndex(Cursor) == getSpeciLineVisLength(Cursor) - 1)
                return; //moded getCurLineLength().
            if (getSpeciCharIndex(Cursor) == getSpeciLineVisLength(Cursor) - 1)
            { //moded getCurLineLength().
                line[getSpeciLineIndex(Cursor)] = getSpeciLineVisStr(Cursor) + line[getSpeciLineIndex(Cursor) + 1];
                ins = line.begin();
                for (int i = 1; i <= getSpeciLineIndex(Cursor); i++)
                    ++ins;
                line.erase(++ins);
                return;
            }
            left = getSpeciCursorLeftSub(Cursor);
            right = getSpeciCursorRightSub(Cursor).substr(1);
            line[getSpeciLineIndex(Cursor)] = left + right;
            break;
        case 2:
            if (getSpeciCharIndex(Cursor) == -1 && getSpeciLineIndex(Cursor) == 0)
                return;
            if (getSpeciCharIndex(Cursor) == -1)
            {
                pos tmpCurs = Cursor; //backup the Cursor. so we can move the Cursor before line is merged.
                Move(3);
                Move(2);
                line[getSpeciLineIndex(tmpCurs) - 1] = getSpeciLineVisStr(pos(tmpCurs.row - 1, tmpCurs.col)) + line[getSpeciLineIndex(tmpCurs)];
                ins = line.begin();
                for (int i = 1; i <= getSpeciLineIndex(tmpCurs); i++)
                    ++ins;
                line.erase(ins);
                return;
            }
            left = getSpeciCursorLeftSub(Cursor).substr(0, getSpeciCharIndex(Cursor));
            right = getSpeciCursorRightSub(Cursor);
            line[getSpeciLineIndex(Cursor)] = left + right;
            --Cursor.col; //Cursor goes back 1 char.
            break;
    }
}

int theFind(string word)
{
    vector<string> range = getSelectionArea();
    int ans = 0;
    for (string curLine : range)
    {
        int fIndex = 0;
        while (fIndex < curLine.length() && (fIndex = curLine.find(word)) != string::npos)
        {
            ++ans;
            curLine = curLine.substr(fIndex + 1);
            fIndex = 0;
        }
    }
    return ans;
}

void shift()
{
    shifted = !shifted;
    if (shifted)
    {
        if (inSelection)
        {
            inSelection = false;
            return;
        }
        remPoint = Cursor;
    }
    else
    {
        if (remPoint == Cursor)
            return;
        if (remPoint < Cursor)
        {
            selection[0] = remPoint;
            selection[1] = Cursor;
        }
        else
        {
            selection[1] = remPoint;
            selection[0] = Cursor;
        }
        inSelection = true;
    }
}

int theCount()
{
    vector<string> range = getSelectionArea();
    int ans = 0;
    for (string str : range)
        for (char c : str)
            if (c != ' ' && c != '\n')
                ans++;
    return ans;
}

void thePrint()
{
    for (string str : line)
        if (!str.empty())
            cout << str;
    cout << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    int opCnt;
    cin >> opCnt;
    line.emplace_back("");
    string op, arg1;
    bool insertChar = false; //for debug.
    for (int opI = 1; opI <= opCnt; opI++)
    {
        insertChar = false;
        cin >> op;
        switch(op[0]){
            case 'M': {
                cin >> arg1;
                switch(arg1[0]){
                    case 'H':{
                        Move(1);
                        break;
                    }
                    case 'E':{
                        Move(2);
                        break;
                    }
                    case 'U':{
                        Move(3);
                        break;
                    }
                    case 'D':{
                        Move(4);
                        break;
                    } 
                    case 'L':{
                        Move(5);
                        break;
                    }
                    case 'R':{
                        Move(6);
                        break;
                    }
                }
         
            break;
            }
            case 'I':
                    {
                        cin >> arg1;
                        switch(arg1[0]){
                            case 'C':{
                                string arg2;
                            cin >> arg2;
                            insert(1, arg2);
                            insertChar = true; // for debug.
                            break;
                            }
                            case 'E':{
                                insert(2, NULLSTR);
                                break;
                            }
                            case 'S':{
                                insert(3, NULLSTR);
                                break;
                            }
                            case 'P':{
                                insert(4, NULLSTR);
                                break;
                            }
                        }
                  
                        break;
                    }
            case 'R': {
                cin >> arg1;
            if (arg1 == "Del")
            {
                theRemove(1);
            }
            else if (arg1 == "Backspace")
            {
                theRemove(2);
            }
            break;
            }
            case 'S':{
                shift();
                break;
            }
            case 'F':{
                cin >> arg1;
            int ans = theFind(arg1);
            cout << ans << endl;
            break;
            }
            case 'C':{
                if(op[2]=='P'){
                    theCopy(pasteBin);
                }else if(op[2]=='U'){
                    cout << theCount() << endl;
                }
                break;
            }
            case 'P':{
                thePrint();
                break;
            }
        }
        
    }
    return 0;
}

4D :?豬國殺(模板)

請使用指定的代碼模板完成該題~

  • 由于原題在題面和數(shù)據(jù)上的一些小問題,本題經(jīng)過了一些小修小改,數(shù)據(jù),和題面,與 SDOI2010 略有不同。參考網(wǎng)絡(luò)資料將讓你在完成作業(yè)的路徑上繞遠(yuǎn)路(不保證可行)并且收獲甚少。相信自己,獨立完成會收獲很多,你也可以在思考無所獲后向同學(xué)請教。
  • 代碼模板精心制作,請大家理解后進(jìn)行補全代碼實驗
    • 本題代碼模板不嚴(yán)格遵守面向?qū)ο蟮囊?guī)則,而是面向教育用途設(shè)計
    • 比起費力優(yōu)化代碼的常數(shù)復(fù)雜度,更樂于精心設(shè)計將代碼邏輯區(qū)分開
  • 本實驗考點:
    • 問題理解及其邏輯化能力
    • 大型(顯然并不大?第三方代碼框架理解和分析能力
    • 工程改動的創(chuàng)口分析和實踐能力
    • 程序調(diào)試能力
  • 期末將近,預(yù)祝同學(xué)們期末考得好成績,不負(fù)努力,加油。

背景

《豬國殺》是一種多豬牌類回合制游戲,一共有 3 種角色:主豬,忠豬,反豬。每局游戲主豬有且只有 1 只,忠豬和反豬可以有多只,每只豬扮演 1 種角色。

目的

主豬 / MP:自己存活的情況下消滅所有的反豬。
忠豬 / ZP:不惜一切保護(hù)主豬,勝利條件與主豬相同。
反豬 / FP:殺死主豬。

游戲過程

游戲開始時,每個玩家手里都會有 4 張牌,且體力上限和初始體力都是 4 。

開始游戲時,從主豬開始,按照逆時針方向(數(shù)據(jù)中就是按照編號從?1,2,3…n?的順序)依次行動。

每個玩家自己的回合可以分為 2 個階段:

  • 摸牌階段:從牌堆頂部摸 2 張牌,依次放到手牌的最右邊;
  • 出牌階段:你可以使用任意張牌,每次使用牌的時候都使用最靠左的能夠使用的牌。當(dāng)然,要滿足如下規(guī)則:
  1. 如果沒有豬哥連弩,每個出牌階段只能使用 1 次「殺」來攻擊;
  2. 任何牌被使用后被棄置(武器是裝備上);被棄置的牌以后都不能再用,即與游戲無關(guān)。

各種牌介紹

每張手牌用 1 個字母表示,字母代表牌的種類。

基本牌

『桃 / P』在自己的回合內(nèi),如果自己的體力值不等于體力上限,那么使用 1 個桃可以為自己補充 1 點體力,否則不能使用桃;桃只能對自己使用;在自己的回合外,如果自己的血變?yōu)?0 或者更低,那么也可以使用。

『殺 / K』在自己的回合內(nèi),對攻擊范圍內(nèi)除自己以外的 1 名角色使用。如果沒有被『閃』抵消,則造成 1 點傷害。無論有無武器,殺的攻擊范圍都是 1。

『閃 / D』當(dāng)你受到殺的攻擊時,可以棄置 1 張閃來抵消殺的效果。

錦囊牌

『決斗 / F』出牌階段,對除自己以外任意 1 名角色使用,由目標(biāo)角色先開始,自己和目標(biāo)角色輪流棄置 1 張殺,首先沒有殺可棄的一方受到 1 點傷害,另一方視為此傷害的來源。

『南豬入侵 / N』出牌階段,對除你以外所有角色使用,按逆時針順序從使用者下家開始依次結(jié)算,除非棄置 1 張殺,否則受到 1 點傷害。

『萬箭齊發(fā) / W』和南豬入侵類似,不過要棄置的不是殺而是閃。

『無懈可擊 / J』在目標(biāo)錦囊生效前抵消其效果。每次有 1 張錦囊即將生效時,從使用這張錦囊的豬開始,按照逆時針順序,依次得到使用無懈可擊的機會;效果:用于決斗時,決斗無效并棄置;用于南豬入侵或萬箭齊發(fā)時,當(dāng)結(jié)算到某個角色時才能使用,當(dāng)前角色不需棄置牌并且不會受到傷害(僅對 1 個角色產(chǎn)生效果);用于無懈可擊時,成為目標(biāo)的無懈可擊被無效。

裝備牌

『豬哥連弩 / Z』武器,攻擊范圍 1 ,出牌階段你可以使用任意張殺; 同一時刻最多只能裝 1 把武器;如果先前已經(jīng)有了 1 把武器,那么之后再裝武器的話,會棄置以前的武器來裝現(xiàn)在的武器。

特殊事件及概念解釋

傷害來源:殺、南豬入侵、萬箭齊發(fā)的傷害來源均是使用該牌的豬,決斗的傷害來源如上;

距離:兩只豬的距離定義為沿著逆時針方向間隔的豬數(shù) +1 。即初始時 1 和 2 的距離為 1 ,但是 2 和 1 的距離就是 n?1 。注意一個角色的死亡會導(dǎo)致一些豬距離的改變;

玩家死亡:如果該玩家的體力降到 0 或者更低,并且自己手中沒有足夠的桃使得自己的體力值回到 1 ,那么就死亡了,死亡后所有的牌(裝備區(qū),手牌區(qū))被棄置

獎勵與懲罰:反豬死亡時,最后一個傷害來源處(即使是反豬)立即摸 3 張牌。忠豬死亡時,如果最后一個傷害來源是主豬,那么主豬所有裝備牌、手牌被棄置。

注意:一旦達(dá)成勝利條件,游戲立刻結(jié)束,因此即使會摸 3 張牌或者還有牌可以用也不用執(zhí)行了。

現(xiàn)在,我們已經(jīng)知道每只豬的角色、手牌,還有牌堆初始情況,并且假設(shè)每個角色會按照如下的行為準(zhǔn)則進(jìn)行游戲,你需要做的就是告訴最后的結(jié)果。

幾種行為:

獻(xiàn)殷勤:使用無懈可擊擋下南豬入侵、萬箭齊發(fā)、決斗;使用無懈可擊抵消表敵意的錦囊效果;
表敵意:對某個角色使用殺、決斗;使用無懈可擊抵消獻(xiàn)殷勤的錦囊效果;
跳忠:即通過行動表示自己是忠豬。跳忠行動就是對主豬或?qū)δ持灰呀?jīng)跳忠的豬獻(xiàn)殷勤,或者對某只已經(jīng)跳反的豬表敵意;
跳反:即通過行動表示自己是反豬。跳反行動就是對主豬或?qū)δ持灰呀?jīng)跳忠的豬表敵意,或者對某只已經(jīng)跳反的豬獻(xiàn)殷勤。

注意:忠豬不會跳反,反豬也不會跳忠;不管是忠豬還是反豬,能夠跳必然跳。

行動準(zhǔn)則

共性

  • 每個角色如果手里有桃且生命值未滿,那么必然吃掉;
  • 有南豬入侵、萬箭齊發(fā)、必然使用;有裝備必然裝上;
  • 受到殺時,有閃必然棄置;
  • 響應(yīng)南豬入侵或者萬箭齊發(fā)時候,有殺 / 閃必然棄置;
  • 不會對未表明身份的豬獻(xiàn)殷勤(包括自己)。

特性

主豬:

  • 主豬會認(rèn)為「沒有跳身份,且用南豬入侵 / 萬箭齊發(fā)對自己造成傷害的豬」是類反豬(沒傷害到不算,注意類反豬并沒有表明身份),如果之后跳了,那么主豬會重新認(rèn)識這只豬;
  • 對于每種表敵意的方式,對逆時針方向能夠執(zhí)行到的第一只已跳反豬表;如果沒有,對逆時針方向能夠執(zhí)行到的第一只類反豬表,再沒有,那么就不表敵意;
  • 決斗時會不遺余力棄置殺;
  • 如果能對已經(jīng)跳忠的豬或自己獻(xiàn)殷勤,那么一定獻(xiàn);如果能夠?qū)σ呀?jīng)跳反的豬表敵意,那么一定表。

忠豬:

  • 對于每種表敵意的方式,對「逆時針方向能夠執(zhí)行到的第一只已經(jīng)跳反的豬」表,如果沒有,那么就不表敵意;
    決斗時,如果對方是主豬,那么不會棄置殺,否則,會不遺余力棄置殺;
  • 如果有機會對主豬或者已經(jīng)跳忠的豬獻(xiàn)殷勤,那么一定獻(xiàn)。

反豬:

  • 對于每種表敵意的方式,如果有機會則對主豬表,否則,對「逆時針方向能夠執(zhí)行到的第一只已經(jīng)跳忠的豬」表,如果沒有,那么就不表敵意;
  • 決斗時會不遺余力棄置殺;
  • 如果有機會對已經(jīng)跳反的豬獻(xiàn)殷勤,那么一定獻(xiàn)。

輸入格式

輸入文件第一行包含兩個正整數(shù)?n(2?n?10)?和?m(m?2000),分別代表玩家數(shù)和牌堆中牌的數(shù)量。數(shù)據(jù)保證牌的數(shù)量夠用。

接下來 n 行,每行 5 個字符串,依次表示對第 i 只豬的角色和初始 4 張手牌描述。編號為 1 的肯定是主豬。

再接下來一行,一共 m 個字符串,按照從牌堆頂部到牌堆底部的順序描述每張牌。

注意:所有的相鄰的兩個字符串都嚴(yán)格用 1 個空格隔開,行尾沒有多余空格。

輸出格式

輸出數(shù)據(jù)第一行包含一個字符串代表游戲結(jié)果。如果是主豬勝利,那么輸出 MP ,否則輸出 FP 。數(shù)據(jù)保證游戲總會結(jié)束。

接下來 n 行,第 i 行是對第 i 只豬的手牌描述(注意只需要輸出手牌),按照手牌從左往右的順序輸出,相鄰兩張牌用 1 個空格隔開,行末尾沒有多余空格。如果這只豬已陣亡,那么只要輸出 DEAD 即可。

注意:如果要輸出手牌而沒有手牌的話,那么只需輸出 1 個空行。

樣例

Input:

3 10
MP D D F F
ZP N N N D
FP J J J J
F F D D J J F F K D

Output:

FP
DEAD
DEAD
J J J J J J D

解釋:

  • 第一回合:

    • 主豬沒有目標(biāo)可以表敵意;
    • 接下來忠豬使用了 3 張南豬入侵,主豬掉了 3 點體力,并認(rèn)為該角色為類反豬,3 號角色盡管手里有無懈可擊,但是因為自己未表明身份,所以同樣不能對自己用,乖乖掉 3 點體力;
  • 下一回合:

    • 反豬無牌可出;
    • 接下來主豬對著類反豬爆發(fā),使用 4 張決斗,忠豬死亡,結(jié)果主豬棄掉所有牌;

子任務(wù)

一共 20 組測試數(shù)據(jù),每個點 5 分。

10% 的數(shù)據(jù)沒有錦囊牌,另外 20% 的數(shù)據(jù)沒有無懈可擊。

測試樣例

樣例 1

輸入:

3 25
MP K K K K
ZP Z Z Z Z
FP J J J J
K K Z Z J J K K W Z W W K Z J J K K J J K K W W W

輸出:文章來源地址http://www.zghlxwxcb.cn/news/detail-418515.html

FP
DEAD
DEAD
J J J J J J J J J J W

解答

// 殺
bool Pig::useK(){
    Pig *nxt = getNextPig(); // 獲取下一只豬
    // 判斷使用殺的豬是什么身份
    if(this->type == 'M'){ // 主豬
        if(nxt->jumpType == 'f' or nxt->jumpType=='F'){ // 判斷下一只豬的跳的身份
            nxt->cost(this, 'D');
            return true;
        }
    }else if(this->type=='Z'){ // 忠豬
        if(nxt ->jumpType=='F'){ // 陣營為F則使用
            nxt->cost(this, 'D');
            this->jumpType = 'Z';
            return true;
        }
    }else if(this->type=='F'){ // 反豬
        if(nxt->jumpType=='Z'){ // 判斷是否是忠豬陣營
            nxt->cost(this, 'D');
            this->jumpType = 'F';
            return true;
        }
    }
    return false;
}

// 南蠻入侵
bool Pig::useN() {
    for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
        // TODO: 補全代碼
        if(!nxt->findJ(this)){ // 沒有人使用無懈可擊
            bool dd = nxt->cost(this, 'K');
            if(!dd and nxt->type=='M' and this->jumpType==0){ // 沒有跳身份
                this->jumpType = 'f';
            }
        }
    }
    return true;
}

// 萬箭齊發(fā)
bool Pig::useW() {
    for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
        // TODO: 補全代碼
        if(!nxt->findJ(this)){ // 沒人使用無懈可擊
            bool dd = nxt->cost(this, 'D');
            if(!dd and nxt->type=='M' and this->jumpType==0){ // 沒有跳身份
                this->jumpType = 'f';
            }
        }
    }
    return true;
}

// 決斗
bool Pig::useF(){
    char rr = this->type;
    // int gg = this->index; // 
    if(rr == 'Z'){ // 判斷使用者身份
        int ff;
        bool pp = false;
        Pig *it;
        for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
            if(nxt->jumpType=='F'){
                // ff = nxt->index;
                it = nxt;
                pp = true;
                break;
            }
        }
        if(!pp){
            return false;
        }
        this->jumpType = 'Z';
        if(!it->findJ(this)){ // 判斷是否有人使用無懈可擊
            while(true){
                if(!it->cost(this, 'K')) // 進(jìn)行決斗,兩個人相互出殺
                    break;
                if(!this->cost(it,'K'))
                    break;
            }
        }
        return true;
    }else if(rr == 'F'){
        this->jumpType = 'F';
        if(!ps[0].findJ(this)){ 
            while(true){
                if(!ps[0].cost(this,'K'))
                    break;
                if(!this->cost(&ps[0],'K'))
                    break;
            }
        }
        
        return true;
    }else if(rr == 'M'){
        int lf=100000, ff=100000;
        // 尋找第一個F和f
        for (Pig* nxt = getNextPig(); nxt != this; nxt = nxt->getNextPig()) {
            if(nxt->jumpType=='F'){
                if(nxt->index < ff){
                    ff = nxt->index;
                }   
            }
            if(nxt->jumpType =='f'){
                if (lf > nxt->index){
                    lf = nxt->index;
                }
            }
        }
        // 有F存在時
        if(ff < n){
            if(!ps[ff].findJ(this)){
                while(true){
                    if(!ps[ff].cost(this,'K'))
                    break;
                        // return true;
                    if(!this->cost(&ps[ff],'K'))
                    break;
                        // return true;
                }
            }
            return true;
        }else if(lf < n){ // F不存在,但是f存在時
            if(!ps[lf].findJ(this)){
                if(ps[lf].type == 'Z'){
                    ps[lf].hurt(this);
                }else{
                    while(true){
                        if(!ps[lf].cost(this,'K'))
                        // return true;
                            break;
                        if(!this->cost(&ps[lf],'K'))
                            break;
                        // return true;
                    }    
                }
            }
            return true;
        }
    }
    return false;
}

// 刪除一張牌
bool Pig::del(char c){
    // Pig *nxt = getNextPig();
    // int gg = this->index;
    for (list<char>::iterator i = this->cards.begin(); i != this->cards.end();i++){ // 尋找牌
        if(c != *i)
            continue;
        else{ // 有就刪除,沒有就返回false
            this->cards.erase(i);
            return true;
        }
    }
    return false;
}

到了這里,關(guān)于Vj程序設(shè)計復(fù)雜模擬題訓(xùn)練的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • hw大一Python模擬題詳解

    hw大一Python模擬題詳解

    一、選擇題 1、關(guān)于Python語言的特點,以下選項描述正確的是( B )。 A.Python語言不支持面向?qū)ο蟆??????????? B.Python語言是解釋型語言。 C.Python語言是編譯型語言。????????????? D.Python語言是非跨平臺語言。 解析: Python 是一種解釋型、面向?qū)ο蟆討B(tài)數(shù)據(jù)類型

    2024年01月16日
    瀏覽(21)
  • 藍(lán)橋杯嵌入式--實戰(zhàn)模擬題

    藍(lán)橋杯嵌入式--實戰(zhàn)模擬題

    在藍(lán)橋杯省賽舉辦之前,學(xué)校組織了一場模擬賽,基于第十三屆的省賽題,但是難度略高于省賽,這篇博客記錄一下解題的過程,其思路可供大家參考。 詳細(xì)工程目前先聯(lián)系我獲取。 花個十幾分鐘把題目好好理解一下,然后先整理出一個大體的運行原理。很容易我們就想到

    2023年04月10日
    瀏覽(36)
  • 736. Lisp 語法解析 : DFS 模擬題

    這是 LeetCode 上的 736. Lisp 語法解析 ,難度為 困難 。 Tag : 「DFS」、「模擬」、「哈希表」 給你一個類似 Lisp 語句的字符串表達(dá)式 expression ,求出其計算結(jié)果。 表達(dá)式語法如下所示: 表達(dá)式可以為整數(shù), let 表達(dá)式, add 表達(dá)式, mult 表達(dá)式,或賦值的變量。表達(dá)式的結(jié)果總是

    2024年02月03日
    瀏覽(22)
  • 軟考高項:信息網(wǎng)絡(luò)安全模擬題

    280、在TCP/IP的體系架構(gòu)中,ARP協(xié)議位于(),它的作用是()。 A.網(wǎng)絡(luò)層將MAC地址解析為IP地址 B.鏈路層將MAC地址解析為IP地址 C.網(wǎng)絡(luò)層將IP地址解析為MAC地址 D.鏈路層將lP地址解析為MAC地址 正確答案:D 解析:在TCP/IP的體系架構(gòu)中,ARP協(xié)議位于鏈路層,它的作用是將IP地址解析為MAC地址

    2024年02月13日
    瀏覽(26)
  • Vj程序設(shè)計作業(yè)H7

    問題描述 在一條街上有 n 個賣菜的商店,按 1 至 n 的順序排成一排,這些商店都賣一種蔬菜。 第一天,每個商店都自己定了一個價格。店主們希望自己的菜價和其他商店的一致,第二天,每一家商店都會根據(jù)他自己和相鄰商店的價格調(diào)整自己的價格。具體的,每家商店都會

    2023年04月26日
    瀏覽(33)
  • csp-j/s模擬題詳細(xì)題解

    題目描述 一天小理買了N個容量可以認(rèn)為是無限大的瓶子,開始時每個瓶子里有1升水。接著小理發(fā)現(xiàn)瓶子實在太多了,于是他決定保留不超過K個瓶子,每次他選擇兩個當(dāng)前含水量相同的瓶子合并。(即把一個瓶子的水全部倒進(jìn)另一個里然后把空瓶丟棄) (注:不能丟棄有水

    2024年02月10日
    瀏覽(25)
  • 軟考高項:信息網(wǎng)絡(luò)安全知識模擬題

    620、以下哪個場景屬于身份鑒別過程()。 A.用戶依照提示輸入用戶名、口令和短信驗證碼,成功登錄該應(yīng)用。 B.用戶在網(wǎng)絡(luò)上共享了的一份加密的pdf文檔,以阻止其他人下載查看文檔中的內(nèi)容。 C.用戶給自己編寫的文檔加上水印。 D.用戶在網(wǎng)上下載了一份帶水印的文檔,去掉

    2024年02月05日
    瀏覽(21)
  • 國家信息安全水平考試NISP一級模擬題

    1. ? 下列關(guān)于用戶口令說法錯誤的是 ( ? ) 。 A. ? 口令不能設(shè)置為空 B. ? 口令長度越長, ? 安全性越高 C. ? 復(fù)雜口令安全性足夠高,不需要定期修改 D. ? 口令認(rèn)證是最常見的認(rèn)證機制 正確答案: ? C 2. ? 下列關(guān)于木馬病毒的特性, ? 不正確的是 ( ? ) 。 A. ? 隱蔽

    2023年04月08日
    瀏覽(19)
  • 網(wǎng)絡(luò)安全模擬題----軟考高項的走過來

    1、某公司技術(shù)人員利于自己的技術(shù)入侵了某電商數(shù)據(jù)庫,將其中的用戶數(shù)據(jù)下載后在暗網(wǎng)中進(jìn)行售賣,該行為的處置最適用的是以下那部法律?(??) A.刑法????B.網(wǎng)絡(luò)安全法?????C.電子簽名法?????D.勞動法 正確答案:A?????解析:入侵他人網(wǎng)站,角觸犯的是刑法,不屬于

    2024年02月10日
    瀏覽(20)
  • 藍(lán)橋杯web開發(fā)-5道模擬題讓你信心滿滿

    藍(lán)橋杯web開發(fā)-5道模擬題讓你信心滿滿

    ?? 作者簡介:大家好,我是阿牛,全棧領(lǐng)域新星創(chuàng)作者。?? ?? 個人主頁:館主阿牛?? ?? 支持我:點贊??+收藏??+留言?? ?? 系列專欄:硬泡 javascript?? ??格言:迄今所有人生都大寫著失敗,但不妨礙我繼續(xù)向前!?? 前些天發(fā)現(xiàn)了一個比較好的人工智能學(xué)習(xí)網(wǎng)站,

    2023年04月09日
    瀏覽(45)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包