XJOIシミュレーショントレーニング22

A.マインスイーパ(掃海艇)

件名の説明:

あなたは順番にプレイヤーが操作を読み、対応する結果を返す、地図情報が取得され、地雷除去の相互作用を記述する必要があります。
地雷除去状況は、いくつかの場所といくつかの地雷クリア位置は、状況がマトリクス状に入力された文字を地雷除去しますM×Nの矩形です。第i行j列の位置は⟨i、j⟩として示されます。具体的には、0 <K <N M×確保、kは地雷の数とします。
最初のプレーヤーはN、M、k個の地雷除去状況を除いては何も知ることができません。
あなたはマップの文字行列命名プレーヤー、すべての要素の初期行列_(アンダースコア)を維持する必要があります。

プレイヤーはq倍のだろう操作するたびに場所を選択、(⟨x、y⟩\)\を、以下の3つの方法のいずれかをクリックしてください(ゲームオーバーであれば、あなたがゲームの終了後に作動するすべてのプレイヤーを無視すべきで、それはこれらと判断されます操作無効操作)有効な操作とその逆です。

  1. 左クリック:場合は\(⟨x、\y⟩)が開かれているかプレイヤーマップこの場所はPである(Pフラグを表す)、何もしない、それ以外の場合は、もし\(⟨x、\y⟩)鉱山に、ゲームが失敗し、そうでないために(⟨x、y⟩\)\開放動作を。
  2. 右クリック:場合は\(⟨x、\y⟩)が開かれている、何も行われません。そうでない場合は、プレイヤーのマップの場所の場合は\(\y⟩、⟨xは) ** _です(アンダースコア)、そのプレイヤーマップ位置場合、Pに変更\は(⟨x、y⟩\) Pであり、プレイヤーマップ位置場合?に変更\(⟨x、y⟩\) _読み取ること?です。
  3. ボタンをクリックしてください:場合は\は(⟨x、y⟩\)オープンされていない、または8を配置するように隣接する位置の周りのプレイヤーPマップの数がプレイヤーをマップでの位置の値と等しくない、何もしません動作は、そうでなければため\(⟨x、y⟩\)鉱山の少なくとも1つの位置がある場合、隣接する8周りに回動されておらず、プレイヤがPのマップの位置ではなく、ゲームに失敗し、そうでない場合はこれらの位置に開いて。

開放操作:位置(⟨x、y⟩\)\次のように開動作が行われます。

  1. \は(⟨x、y⟩\)などのオープンマーク。
  2. プレイヤーマップ位置\(⟨x、y⟩\)の代わりにC(0≤C≤8) 、位置8の周りに地雷の数は、隣接位置ことを示しています。
  3. C = 0の場合は、その隣接する8つのマップの周りに開いていないとプレイヤがPポジション開動作していません。
  4. この操作は考慮操作のこの開放端の終了後にすべてのサブオペレーションまで、再帰的に実行されます。

ゲームオーバー、以下の3つの条件を超えるゲーム:

  1. ゲームオーバー:それはルールの上にある、位置を操作するなどのオープン鉱山になろうとすると、ゲームが失敗する原因になります。
  2. ゲーム勝利:操作の終了後の時間は、場所の数は正確にk個、勝利後のゲームの操作を開いていない場合。
  3. プレーヤーの操作が終了した場合は、両方のケースがあり、その後、ゲームのうちのプレーヤーと見なされていなかった:ゲームを終了します。

各操作の後、あなたがする必要がある結果を返す、次のように、特定のルールは以下のとおりです。

  • この操作は無効な操作である場合は、INVALIDを返し、そうでない場合
  • 操作が失敗した場合は試合後、リターンはLOSE、そうでない場合
  • RUNNING:; X最初のキーの座標の位置に応じて変化し、同じ行に含まれるブラケットとリターンに戻り、プレイヤが<、X、Yのval>の形式に変更するための位置と値をマッピングを有します第二のキーワード昇順の大きい、y座標に小さいから、隣り合うと位置を変更する、離間。一定時間の後、例えば、動作が戻ってもよい:RUNNING:[];またはRUNNING:[<3,3、?>]。空間位置に注意してください。
  • この操作ゲームの勝利後の場合は、新しい行にWINに戻ります。
  • この操作後のゲームのうち場合は、新しい行にQUITを返します。

入力フォーマット:

入力ファイルは、複数のデータセットが含まれています。
正の整数であり、Tの最初の行は、データセットの数、データのセットを(以下意味)+のQ + 2 n個当たり次の行を表します。
nは2つの正の整数の各セットの最初の行は、高さと幅地雷除去状況を表すそれぞれMです。
Nは、次に、各データのライン、長さmの列のi番目の行、およびのみ_含ま\(* \) 2つの文字を。
j番目の文字が*である場合には、i行目や鉱山などJ、そうでない場合はオープンスペース。
次いで、複数のデータ線の各セットは、各ライン3つの正の整数OPは、X、Yは、説明タイトルを参照し、プレイヤの操作、特定の操作を表します。
それぞれの最後の行の0の数は、プレイヤの操作の終了を表します。プレイヤーはQに操作の数を作ります。

出力フォーマット:

各試験のために、複数の出力線は、それぞれのラインは、復帰動作の結果を表す場合の後、単一の操作、ゲームの終了、出力対応する結果。
二つの隣接するデータ間のラインを使用して(============== \)\(= 10の文字は、引用符なしで)離れ。

データ範囲:

全ての試験点について:1≤T≤30,3≤N、10000≤200,0≤Q≤M、演算∈{1、2、3}、1≤X≤N、Yさ≤M≤1。

解決 :

まれに行いません良いシミュレーションタイトル、
それぞれの場合の対象はすでにイタリアは強くうまくによってシミュレートすることを、非常に明確に記載されています。
無効な操作の定義原因バースト= W =ゼロが表示されません

コード:

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define fr(i, a, b) for(int (i) = (a); (i) <= (b); (i)++)
typedef pair<int, int> pii;
typedef pair<pii, int> pli;
const int N = 205;
int n, m, T, close;
char s[N][N], a[N][N];
vector<pli> prt;
template <class T> void read(T &x) {
    bool f = false; x = 0;
    char ch = getchar();
    while (ch<'0' || ch>'9') {if (ch == '-') f = true; ch = getchar();}
    while (ch>='0' && ch<='9') x = x * 10 + ch - '0', ch = getchar();
    if (f) x = -x;
}
inline void open(int x, int y) {
    close --;
    int cnt = 0;
    fr(i, x - 1, x + 1) fr(j, y - 1, y + 1) {
        if (i < 1 || i > n || j < 1 || j > m) continue;
        if (a[i][j] == '*') cnt++;
    }
    prt.pb(mp(mp(x, y), cnt));
    s[x][y] = '0' + cnt;
    if (cnt == 0) {
        fr(i, x - 1, x + 1) fr(j, y - 1, y + 1) {
            if (i < 1 || i > n || j < 1 || j > m) continue;
            if (s[i][j] == '_' || s[i][j] == '?') {
                open(i, j);
            }
        }
    }
}
inline void shuchu() {
    sort(prt.begin(), prt.end());
    int sz = prt.size() - 1;
    printf("RUNNING: [");
    fr(i, 0, sz) {
        printf("<%d, %d, %d>", prt[i].fi.fi, prt[i].fi.se, prt[i].se);
        if (i != sz) printf(", ");
    }
    puts("]");
}
int main() {
    read(T);
    while (T--) {
        read(n), read(m);
        int mine = 0;
        fr(i, 1, n) {
            scanf("%s", a[i] + 1);
            fr(j, 1, m) if (a[i][j] == '*') mine++;
        }
        fr(i, 1, n) fr(j, 1, m) s[i][j] = '_';
        int op, x, y; close = n * m;
        bool lose = false, win = false;
        while (~scanf("%d", &op)) {
            if (op == 0) {
                if (!win && !lose) puts("QUIT");
                break;
            }
            read(x), read(y);
            if (lose || win) {puts("INVALID"); continue;}
            if (op == 1) {
                if (s[x][y] >= '0' && s[x][y] <= '9' || s[x][y] == 'P')  {puts("RUNNING: []"); continue;}
                if (a[x][y] == '*') {
                    puts("LOSE"); lose = true;
                    continue;
                }
                prt.clear();
                open(x, y); shuchu();
                if (close == mine) {puts("WIN"); win = true; continue;}
            }
            if (op == 2) {
                if (s[x][y] >= '0' && s[x][y] <= '9')  {puts("RUNNING: []"); continue;}
                if (s[x][y] == '_') s[x][y] = 'P';
                else if (s[x][y] == 'P') s[x][y] = '?';
                     else s[x][y] = '_';
                printf("RUNNING: [<%d, %d, %c>]\n", x, y, s[x][y]);
            }
            if (op == 3) {
                if (!(s[x][y] >= '0' && s[x][y] <= '9')) {puts("RUNNING: []"); continue;}
                int cnt = 0;
                fr(i, x - 1, x + 1) fr(j, y - 1, y + 1) {
                    if (i < 1 || i > n || j < 1 || j > m) continue;
                    if (s[i][j] == 'P') cnt++;
                }
                if (cnt != (s[x][y] - '0')) {puts("RUNNING: []"); continue;}
                prt.clear();
                fr(i, x - 1, x + 1) {
                    fr(j, y - 1, y + 1) {
                        if (i < 1 || i > n || j < 1 || j > m) continue;
                        if (s[i][j] == 'P' || (s[i][j] >= '0' && s[i][j] <= '9')) continue;
                        if (a[i][j] == '*') {
                            lose = true;
                        } else open(i, j);
                    }
                }
                if (lose) {puts("LOSE"); continue;}
                shuchu();
                if (close == mine) {puts("WIN"); win = true; continue;}
            }
        }
        if (T) puts("==========");
    }
    return 0;
}

B.多色木(カラフル)

件名の説明:

与えられた\(\ N-)ツリーのノード、ノード番号\を(1〜N-\) 各ノードは、色に感染している、の合計\(m個\)番号異なる色、\(M 1〜\) 注ノード\(私は\)カラーの\(C_I \) 色のような小さなXは、彼は、通信ツリーの一部を選択したい\(S \) および\(S \)少なくとも含まれている必要がありますノードに\(k個\)異なる色を。その\(S \)が接続され、元のツリーの部分グラフ、およびセットである、満たされなければならない({| U∈S C_Uが\ } \) の少なくともサイズ\(K \) Yは、色が、少し嫌い、彼女はほかにはほとんどXましょう\(S \)をすべてのノードの色のノードの外に消去され、ノードに滞在されている\(U \) 彼女はノードの最大化したい(\をU \)は、ノードと任意の色の間の距離の最小値を有します。それは、最大化される\(分\ {DIS(U、X)\}∈S X \)、\ (DIS(X、Y)\)ノードを示す(X \)\ノード(Y \)\の距離によって定義されるエッジの最小数を通る距離、。Xは、まだ小さな選択を決定していない\(S \)彼はあなたが上記のすべての条件が満たされる必要があり、最大化、あなたになって、プログラムを\(U \)\を(S \)ノードから。

入力フォーマット:

3つの正の整数の最初の行\(N、M、K \)被験者が説明を参照意味します。
第二列\(N- \)は正の整数\(C1 ... N \)に順次各ノードの色を示します。
\(N - 1 \) 2つの正の整数の行\(X、Yの\)は接続ノード表す\(X \)とノード\(Y \)側。

出力フォーマット:

出力行数が最大距離を表します。

例:

エントリー

7 2 2
1 2 2 2 2 1 1
1 2
1 3
1 4
3 5
3 6
6 7

輸出

3

データ範囲:

すべてのデータに対して、\(1≤K≤Mさ≤N-≤10 6 ^ \)、\ (1≤m個の≤のCIの\)

解決 :

木は根のない木で、私たちは、ルートノード、貪欲と思いますが、最後に選出されたサブグラフの1点目厳選\(S \)を 2例があります。

  1. 1サブツリーがルートとされています
  2. 図1は、サブツリーを削除することによって、ルート付きツリーであります

最初のケースでは、最小値がDIS DP見つけることができる
第二のケースを、DFSを指示する最大深さが見つける
我々はDISサブツリーは、それぞれの一点根ざした2例の値を得ることができる
コンタクトを色によってポイントにカウントダウンし、このサブツリーを含まないサブツリー
いくつかのポイントをルートにするサブツリーがシーケンスが連続しているDFSを検討し、そのコピーのDFSは後に、ポイントが省略されていますサブツリーのルートの残りの部分にも連続しているので、我々は、直接二重ポインタkのDFS配列DFSのために処理することができる最初の色の全ての点の位置に到達し、位置が点に含まれるか否かを判断します内部の木がすることができます。

DFS順本当に良いこと=ワット=

コード:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7, inf = 1e9 + 7;
int n, m, k, cnt = 0, inx = 0;
int c[N], ct[N], num[N * 2], in[N], out[N];
int fir[N], nxt[N * 2], to[N * 2], dis[N], Mx[N], pos[N * 2];
inline void AddEdge(int u, int v) {
    nxt[++cnt] = fir[u];
    fir[u] = cnt, to[cnt] = v;
}
void dfs1(int u, int fa) {
    in[u] = ++inx;
    num[inx] = u;
    for (int i = fir[u]; i; i = nxt[i]) {
        int v = to[i];
        if (v == fa) continue;
        dfs1(v, u);
        dis[u] = max(dis[u], dis[v] + 1);
    }
    out[u] = inx;
}
void dfs2(int u, int fa) {
    int mx = 0, cmx = 0;
    for (int i = fir[u]; i; i = nxt[i]) {
        int v = to[i];
        if (v == fa) continue;
        if (dis[v] + 1 >= mx) cmx = mx, mx = dis[v] + 1;
        else cmx = max(cmx, dis[v] + 1);
    }
    for (int i = fir[u]; i; i = nxt[i]) {
        int v = to[i];
        if (v == fa) continue;
        Mx[v] = max(Mx[u] + 1, (dis[v] + 1 == mx) ? cmx + 1 : mx + 1);
        dfs2(v, u);
    }
}
int main() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
    for (int i = 1; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        AddEdge(x, y);
        AddEdge(y, x);
    }
    dfs1(1, 0);
    dfs2(1, 0);
    for (int i = 1; i <= n; i++) num[i + n] = num[i];
    int nw = 0;
    for (int i = 1, j = 1; j <= 2 * n; j++) {
        if (ct[c[num[j]]] == 0) nw ++;
        ct[c[num[j]]] ++;
        while (nw > k || ct[c[num[i]]] > 1) {
            ct[c[num[i]]] --;
            if (ct[c[num[i]]] == 0) nw --;
            i ++;
        }
        if (nw >= k) pos[j] = i;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (pos[out[i]] >= in[i]) ans = max(ans, Mx[i]);
        if (pos[in[i] + n - 1] > out[i]) ans = max(ans, dis[i] + 1);
    }
    printf("%d\n", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/bryane/p/11758100.html