zoukankan      html  css  js  c++  java
  • 【NOIP2015】反思+题解

    D1T1> 神奇的幻方

      模拟即可。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define rep(i, a, b) for (int i = a; i <= b; i++)
     5 #define drep(i, a, b) for (int i = a; i >= b; i--)
     6 #define REP(i, a, b) for (int i = a; i < b; i++)
     7 #define pb push_back
     8 #define mp make_pair
     9 #define clr(x) memset(x, 0, sizeof(x))
    10 #define xx first
    11 #define yy second
    12 
    13 using namespace std;
    14 
    15 typedef long long i64;
    16 typedef pair<int, int> pii;
    17 const int inf = ~0U >> 1;
    18 const i64 INF = ~0ULL >> 1;
    19 //******************************
    20 
    21 int map[55][55];
    22 int main() {
    23     int n;
    24     scanf("%d", &n);
    25     pii last = mp(1, n / 2 + 1);
    26     map[1][n / 2 + 1] = 1;
    27     rep(i, 2, n * n) {
    28         if (last.xx == 1 && last.yy != n) {
    29             map[n][last.yy + 1] = i;
    30             last = mp(n, last.yy + 1);
    31         }
    32         else if (last.yy == n && last.xx != 1) {
    33             map[last.xx - 1][1] = i;
    34             last = mp(last.xx - 1, 1);
    35         }
    36         else if (last.xx == 1 && last.yy == n) {
    37             map[last.xx + 1][last.yy] = i;
    38             last = mp(last.xx + 1, last.yy);
    39         }
    40         else if (last.xx != 1 && last.yy != n && !map[last.xx - 1][last.yy + 1]) {
    41             map[last.xx - 1][last.yy + 1] = i;
    42             last = mp(last.xx - 1, last.yy + 1);
    43         }
    44         else {
    45             map[last.xx + 1][last.yy] = i;
    46             last = mp(last.xx + 1, last.yy);
    47         }
    48     }
    49     rep(i, 1, n) {
    50         rep(j, 1, n) {
    51             if (j != 1) printf(" ");
    52             printf("%d", map[i][j]);
    53         }
    54         puts("");
    55     }
    56     return 0;
    57 }
    View Code

    D1T2> 信息传递

      一个点只有一个出度 => 环不会交叉

      1)dfs找环 2)tarjan找scc

      考试的时候就直接写了tarjan...

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define rep(i, a, b) for (int i = a; i <= b; i++)
     5 #define drep(i, a, b) for (int i = a; i >= b; i--)
     6 #define REP(i, a, b) for (int i = a; i < b; i++)
     7 #define pb push_back
     8 #define mp make_pair
     9 #define clr(x) memset(x, 0, sizeof(x))
    10 #define xx first
    11 #define yy second
    12 
    13 using namespace std;
    14 
    15 typedef long long i64;
    16 typedef pair<int, int> pii;
    17 const int inf = ~0U >> 1;
    18 const i64 INF = ~0ULL >> 1;
    19 //******************************
    20 
    21 const int maxn = 200005;
    22 
    23 struct Ed {
    24     int u, v, nx; Ed() {}
    25     Ed(int _u, int _v, int _nx)
    26         :u(_u), v(_v), nx(_nx) {}
    27 } a[maxn];
    28 int fst[maxn], cnt;
    29 void addedge(int u, int v) {
    30     a[++cnt] = Ed(u, v, fst[u]);
    31     fst[u] = cnt;
    32 }
    33 
    34 int dfn[maxn], low[maxn], Index, vis[maxn];
    35 int stack[maxn], top;
    36 int scc_cnt;
    37 int belong[maxn], size[maxn];
    38 void tarjan(int u) {
    39     dfn[u] = low[u] = ++Index;
    40     vis[u] = 1;
    41     stack[++top] = u;
    42     for (int i = fst[u]; i; i = a[i].nx) {
    43         int v = a[i].v;
    44         if (!dfn[v]) {
    45             tarjan(v);
    46             low[u] = min(low[u], low[v]);
    47         }
    48         else if (vis[v]) {
    49             low[u] = min(low[u], dfn[v]);
    50         }
    51     }
    52     if (dfn[u] == low[u]) {
    53         scc_cnt++;
    54         while (stack[top] != u) {
    55             belong[stack[top]] = scc_cnt;
    56             vis[stack[top]] = 0;
    57             size[scc_cnt]++;
    58             top--;
    59         }
    60         belong[stack[top]] = scc_cnt;
    61         vis[stack[top]] = 0;
    62         size[scc_cnt]++;
    63         top--;
    64     }
    65 }
    66 
    67 int main() {
    68     int n;
    69     scanf("%d", &n);
    70     rep(i, 1, n) {
    71         int id;
    72         scanf("%d", &id);
    73         addedge(i, id);
    74     }
    75 
    76     rep(i, 1, n) {
    77         if (!dfn[i]) tarjan(i);
    78     }
    79 
    80     int ans = 0x3f3f3f3f;
    81     rep(i, 1, scc_cnt) if (size[i] != 1) ans = min(ans, size[i]);
    82     
    83     printf("%d
    ", ans);
    84     return 0;
    85 }
    View Code

    D1T3> 斗地主

      搜索题,以前在contest hunter上见过,没有订正...

      因为1 2 3 4 5不能顺, 1 1 1 2 2 2不能连出,可以在读入时将牌的编号重新分配,只需要将 A 调整到 K 后,2 和 A 断开即可。

      考试的时候想把所有可行的方案预处理出来,压位压在一起,然后状压dp,这样是不可行的,因为方案数多了后时间复杂度会爆炸。

      

      以下代码可以过NOIP官方数据,但是过不了UOJ的加强版题目,会WA,这篇代码的思路主要是在每次判断时,人为地把4张和3张出掉,强剪枝。

     1 #include <bits/stdc++.h>
     2 #define rep(i, a, b) for (register int i = a; i <= b; i++)
     3 #define drep(i, a, b) for (register int i = a; i >= b; i--)
     4 #define REP(i, a, b) for (int i = a; i < b; i++)
     5 #define pb push_back
     6 #define mp make_pair
     7 #define clr(x) memset(x, 0, sizeof(x))
     8 #define xx first
     9 #define yy second
    10 
    11 using namespace std;
    12 
    13 typedef long long i64;
    14 typedef pair<int, int> pii;
    15 const int inf = ~0U >> 1;
    16 const i64 INF = ~0ULL >> 1;
    17 //********************************
    18 
    19 const int maxn = 20;
    20 
    21 inline int read() {
    22     int l = 1, s = 0;
    23     char ch = getchar();
    24     while (ch < '0' || ch > '9') { if (ch == '-') l = -1; ch = getchar(); }
    25     while (ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + ch - '0'; ch = getchar(); }
    26     return l * s;
    27 }
    28 
    29 int poker[maxn];
    30 
    31 int ans = inf;
    32 
    33 void dfs(int);
    34 
    35 void group(int base, int len, int dep) {
    36     rep(st, 1, 13 - len) {
    37         if (poker[st] < base) continue;
    38         int end;
    39         for (end = st; end <= 12; end++) if (poker[end] < base) break;
    40         if (--end - st + 1 < len) continue;
    41         drep(k, end, st + len - 1) {
    42             rep(i, st, k) poker[i] -= base;
    43             poker[0] -= (k - st + 1) * base;
    44             dfs(dep + 1);
    45             rep(i, st, k) poker[i] += base;
    46             poker[0] += (k - st + 1) * base;
    47         }
    48     }
    49 }
    50 
    51 int n, tong[maxn];
    52 
    53 void dfs(int dep) {
    54     if (dep > ans) return;
    55     if (poker[0] == 0) return;
    56     rep(i, 1, 16) tong[poker[i]]++;
    57     int sum(0);
    58     while (tong[4] > 0) {
    59         sum++;
    60         tong[4]--;
    61         if (tong[1] >= 2) tong[1] -= 2;
    62         else if (tong[2] >= 2) tong[2] -= 2;
    63     }
    64     while (tong[3] > 0) {
    65         sum++;
    66         tong[3]--;
    67         if (tong[1] >= 1) tong[1] -= 1;
    68         else if (tong[2] >= 1) tong[2] -= 1;
    69     }
    70     if (tong[1] >= 2 && poker[15] >= 1 && poker[16] >= 1) sum--;
    71     if (sum + tong[1] + tong[2] + dep < ans) ans = sum + tong[1] + tong[2] + dep;
    72     tong[1] = tong[2] = 0;
    73 
    74     group(3, 2, dep);
    75     group(2, 3, dep);
    76     group(1, 5, dep);
    77 }
    78 
    79 int main() {
    80     int T;
    81     T = read(), n = read();
    82     while (T--) {
    83         memset(poker, 0, sizeof(poker));
    84         rep(i, 1, n) {
    85             int rb, id;
    86             id = read(); rb = read();
    87             if (id >= 3 && id <= 13) poker[id - 2]++;
    88             else if (id == 1) poker[12]++;
    89             else if (id == 2) poker[14]++;
    90             else if (id == 0 && poker[15] == 0) poker[15]++;
    91             else poker[16]++;
    92         }
    93         poker[0] = n;
    94         ans = inf;
    95         dfs(0);
    96         printf("%d
    ", ans);
    97     }
    98     return 0;
    99 }
    View Code

      这一篇代码依然可以过NOIP官方数据,但是在UOJ加强版上在第9个extra test上t了,不知道卡时是否可以。

      这个思路考虑了 AAAA2222 在一次出完的情况, 还考虑了在4带2时可以破坏3个一样的牌的情况,分别写出来就好了。

      1 #include <bits/stdc++.h>
      2 #define rep(i, a, b) for (int i = a; i <= b; i++)
      3 #define drep(i, a, b) for (int i = a; i >= b; i--)
      4 #define REP(i, a, b) for (int i = a; i < b; i++)
      5 #define pb push_back
      6 #define mp make_pair
      7 #define clr(x) memset(x, 0, sizeof(x))
      8 #define xx first
      9 #define yy second
     10 
     11 using namespace std;
     12 
     13 typedef long long i64;
     14 typedef pair<int, int> pii;
     15 const int inf = ~0U >> 1;
     16 const i64 INF = ~0ULL >> 1;
     17 //********************************
     18 
     19 const int maxn = 20;
     20 
     21 int poker[maxn];
     22 
     23 int ans = inf;
     24 
     25 void dfs(int dep, int order) {
     26     if (dep > ans) return;
     27     if (dep + poker[0] < ans) ans = dep + poker[0];
     28     if (poker[0] == 0) return;
     29     
     30     //AAABBBCCC
     31     if (order <= 0)
     32     rep(st, 1, 12) {
     33         if (poker[st] < 3) continue;
     34         int end;
     35         for (end = st; end <= 12; end++) if (poker[end] < 3) break;
     36         end--; if (end - st < 1) break;
     37         rep(k, st + 1, end) {
     38             rep(i, st, k) poker[i] -= 3;
     39             poker[0] -= (k - st + 1) * 3;
     40             dfs(dep + 1, 0);
     41             rep(i, st, k) poker[i] += 3;
     42             poker[0] += (k - st + 1) * 3;
     43         }
     44     }
     45 
     46     //AABBCC
     47     if (order <= 1)
     48     rep(st, 1, 12) {
     49         if (poker[st] < 2) continue;
     50         int end;
     51         for (end = st; end <= 12; end++) if (poker[end] < 2) break;
     52         end--; if (end - st + 1 < 3) continue;
     53         rep(k, st + 2, end) {
     54             rep(i, st, k) poker[i] -= 2;
     55             poker[0] -= (k - st + 1) * 2;
     56             dfs(dep + 1, 1);
     57             rep(i, st, k) poker[i] += 2;
     58             poker[0] += (k - st + 1) * 2;
     59         }
     60     }
     61 
     62     //ABCDE
     63     if (order <= 2)
     64     rep(st, 1, 12) {
     65         if (poker[st] < 1) continue;
     66         int end;
     67         for (end = st; end <= 12; end++) if (poker[end] < 1) break;
     68         end--; if (end - st + 1 < 5) continue;
     69         rep(k, st + 4, end) {
     70             rep(i, st, k) poker[i] -= 1;
     71             poker[0] -= k - st + 1;
     72             dfs(dep + 1, 2);
     73             rep(i, st, k) poker[i] += 1;
     74             poker[0] += k - st + 1;
     75         }
     76     }
     77 
     78     //AAAABC
     79     if (order <= 3)
     80     rep(st, 1, 14) {
     81         if (poker[st] < 4) continue;
     82         rep(i, 1, 16) {
     83             if (poker[i] < 1 || i == st) continue;
     84             poker[i] -= 1;
     85             rep(j, i, 16) {
     86                 if (poker[j] < 1 || j == st) continue;
     87                 poker[st] -= 4; poker[j] -= 1;
     88                 poker[0] -= 6;
     89                 dfs(dep + 1, 3);
     90                 poker[st] += 4; poker[j] += 1;
     91                 poker[0] += 6;
     92             }
     93             poker[i] += 1;
     94         }
     95     }
     96 
     97     //AAAABBCC
     98     if (order <= 4)
     99     rep(st, 1, 14) {
    100         if (poker[st] < 4) continue;
    101         rep(i, 1, 14) {
    102             if (poker[i] < 2 || i == st) continue;
    103             poker[i] -= 2;
    104             rep(j, i, 14) {
    105                 if (poker[j] < 2 || j == st) continue;
    106                 poker[st] -= 4, poker[j] -= 2;
    107                 poker[0] -= 8;
    108                 dfs(dep + 1, 4);
    109                 poker[st] += 4, poker[j] += 2;
    110                 poker[0] += 8;
    111             }
    112             poker[i] += 2;
    113         }
    114     }
    115 
    116     //AAABB
    117     if (order <= 5)
    118     rep(st, 1, 14) {
    119         if (poker[st] < 3) continue;
    120         rep(i, 1, 14) {
    121             if (poker[i] < 2 || i == st) continue;
    122             poker[st] -= 3, poker[i] -= 2;
    123             poker[0] -= 5;
    124             dfs(dep + 1, 5);
    125             poker[st] += 3, poker[i] += 2;
    126             poker[0] += 5;
    127         }
    128     }
    129 
    130     //AAAB
    131     if (order <= 6)
    132     rep(st, 1, 14) {
    133         if (poker[st] < 3) continue;
    134         rep(i, 1, 16) {
    135             if (poker[i] < 1 || i == st) continue;
    136             poker[st] -= 3, poker[i] -= 1;
    137             poker[0] -= 4;
    138             dfs(dep + 1, 6);
    139             poker[st] += 3, poker[i] += 1;
    140             poker[0] += 4;
    141         }
    142     }
    143 
    144     //AAAA
    145     if (order <= 7)
    146     rep(st, 1, 14) {
    147         if (poker[st] < 4) continue;
    148         poker[st] -= 4, poker[0] -= 4;
    149         dfs(dep + 1, 7);
    150         poker[st] += 4, poker[0] += 4;
    151     }
    152 
    153     //AAA
    154     if (order <= 8)
    155     rep(st, 1, 14) {
    156         if (poker[st] < 3) continue;
    157         poker[st] -= 3, poker[0] -= 3;
    158         dfs(dep + 1, 8);
    159         poker[st] += 3, poker[0] += 3;
    160     }
    161 
    162     //AA
    163     if (order <= 9)
    164     rep(st, 1, 14) {
    165         if (poker[st] < 2) continue;
    166         poker[st] -= 2, poker[0] -= 2;
    167         dfs(dep + 1, 9);
    168         poker[st] += 2, poker[0] += 2;
    169     }
    170 
    171     //Joker
    172     if (order <= 10)
    173     if (poker[15] && poker[16]) {
    174         poker[15] = poker[16] = 0;
    175         poker[0] -= 2;
    176         dfs(dep + 1, 10);
    177         poker[15] = poker[16] = 1;
    178         poker[0] += 2;
    179     }
    180 }
    181 
    182 int main() {
    183     int T, n;
    184     scanf("%d%d", &T, &n);
    185     while (T--) {
    186         memset(poker, 0, sizeof(poker));
    187         rep(i, 1, n) {
    188             int rb, id;
    189             scanf("%d%d", &id, &rb);
    190             if (id >= 3 && id <= 13) poker[id - 2]++;
    191             else if (id == 1) poker[12]++;
    192             else if (id == 2) poker[14]++;
    193             else if (id == 0 && poker[15] == 0) poker[15]++;
    194             else poker[16]++;
    195         }
    196         poker[0] = n;
    197         ans = inf;
    198         dfs(0, 0);
    199         printf("%d
    ", ans);
    200     }
    201     return 0;
    202 }
    View Code

    D2T1> 跳石头

      二分+贪心。

      noi.openjudge.cn的原题,首先二分答案,在二分答案的情况下,扫一遍n个石头,如果这个石头与前一个石头的距离小于二分的答案,那么就把前一个石头取消。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define rep(i, a, b) for (int i = a; i <= b; i++)
     5 #define drep(i, a, b) for (int i = a; i >= b; i--)
     6 #define REP(i, a, b) for (int i = a; i < b; i++)
     7 #define pb push_back
     8 #define mp make_pair
     9 #define clr(x) memset(x, 0, sizeof(x))
    10 #define xx first
    11 #define yy second
    12 
    13 using namespace std;
    14 
    15 typedef long long i64;
    16 typedef pair<int, int> pii;
    17 const int inf = ~0U >> 1;
    18 const i64 INF = ~0ULL >> 1;
    19 //******************************
    20 
    21 int map[55][55];
    22 int main() {
    23     int n;
    24     scanf("%d", &n);
    25     pii last = mp(1, n / 2 + 1);
    26     map[1][n / 2 + 1] = 1;
    27     rep(i, 2, n * n) {
    28         if (last.xx == 1 && last.yy != n) {
    29             map[n][last.yy + 1] = i;
    30             last = mp(n, last.yy + 1);
    31         }
    32         else if (last.yy == n && last.xx != 1) {
    33             map[last.xx - 1][1] = i;
    34             last = mp(last.xx - 1, 1);
    35         }
    36         else if (last.xx == 1 && last.yy == n) {
    37             map[last.xx + 1][last.yy] = i;
    38             last = mp(last.xx + 1, last.yy);
    39         }
    40         else if (last.xx != 1 && last.yy != n && !map[last.xx - 1][last.yy + 1]) {
    41             map[last.xx - 1][last.yy + 1] = i;
    42             last = mp(last.xx - 1, last.yy + 1);
    43         }
    44         else {
    45             map[last.xx + 1][last.yy] = i;
    46             last = mp(last.xx + 1, last.yy);
    47         }
    48     }
    49     rep(i, 1, n) {
    50         rep(j, 1, n) {
    51             if (j != 1) printf(" ");
    52             printf("%d", map[i][j]);
    53         }
    54         puts("");
    55     }
    56     return 0;
    57 }
    View Code

    D2T2> 子串

      dp。

      用f[i][j][k][2]表示第一个字符串中的前i位,取出k段,按顺序组合,拼出第二个字符串前j位的方案数,最后一位若为1则表示第i位被考虑在内(被选取),为0则为不被选取。

      那么当S[i] == T[j]时(S 为 第一个字符串,T 为 第二个字符串)

        f[i][j][k][1] = f[i - 1][j - 1][k][1] + f[i - 1][j - 1][k - 1][0] + f[i - 1][j - 1][k - 1][1];

        f[i][j][k][0] = f[i - 1][j][k][0];

      否则 f[i][j][k][1] = 0, f[i][j][k][0] = f[i - 1][j][k][0] + f[i - 1][j][k][1];

      解释:当前字符能否接下去(假若S[i] ==T[j])实则取决于第i - 1个字符是否选取。

     1 #include <bits/stdc++.h>
     2 #define rep(i, a, b) for (int i = a; i <= b; i++)
     3 #define drep(i, a, b) for (int i = a; i >= b; i--)
     4 #define REP(i, a, b) for (int i = a; i < b; i++)
     5 #define pb push_back
     6 #define mp make_pair
     7 #define clr(x) memset(x, 0, sizeof(x))
     8 #define xx first
     9 #define yy second
    10 
    11 using namespace std;
    12 
    13 typedef long long i64;
    14 typedef pair<int, int> pii;
    15 const int inf = ~0U >> 1;
    16 const i64 INF = ~0ULL >> 1;
    17 //*******************************
    18 
    19 const int maxn = 1005, maxm = 205;
    20 const int mod = 1000000007;
    21 
    22 int read() {
    23     int s = 0, l = 1;
    24     char ch = getchar();
    25     while (ch < '0' || ch > '9') { if (ch == '-') l = -1; ch = getchar(); }
    26     while (ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + ch - '0'; ch = getchar(); }
    27     return l * s;
    28 }
    29 
    30 char str1[maxn], str2[maxm];
    31 i64 f[2][maxm][maxm][2];
    32 
    33 int main() {
    34     int n, m, k;
    35     n = read(), m = read(), k = read();
    36     scanf("%s%s", str1 + 1, str2 + 1);
    37     f[0][0][0][0] = f[1][0][0][0] = 1;
    38     int flag = 0;
    39     rep(i, 1, n) {
    40         flag ^= 1;
    41         int up = min(i, m);
    42         rep(j, 1, up) {
    43             if (str1[i] == str2[j]) rep(kk, 1, j) {
    44                 f[flag][j][kk][0] = (f[1 ^ flag][j][kk][0] + f[1 ^ flag][j][kk][1]) % mod;
    45                 f[flag][j][kk][1] = (f[1 ^ flag][j - 1][kk][1] + f[1 ^ flag][j - 1][kk - 1][0] + f[1 ^ flag][j - 1][kk - 1][1]) % mod;
    46             }
    47             else rep(kk, 1, j) {
    48                 f[flag][j][kk][0] = (f[1 ^ flag][j][kk][0] + f[1 ^ flag][j][kk][1]) % mod;
    49                 f[flag][j][kk][1] = 0;
    50             }
    51         }
    52     }
    53     printf("%lld
    ", (f[flag][m][k][0] + f[flag][m][k][1]) % mod);
    54     return 0;
    55 }
    View Code

    D2T3> 运输计划

      两天内改完......

    总结:考得挺扯蛋的,335,非常不满意:(

      暴力分没有拿全,对算法的掌握不够深刻,最恶心的是做过的题也不会。

      这TM混蛋的人生又干掉了我的希望,就这样吧,也没什么好说的...

  • 相关阅读:
    防抖节流函数
    富文本编辑器tinymce在vue中的使用
    vue脚手架中检测lodop安装情况
    打印插件LODOP Vue中的使用
    vue打包后刷新页面报错:Unexpected token <
    Bootstrap-table表格插件的使用方法
    jsTree树插件
    Vue监控器watch的全面解析
    Vue计算属性computed的全面解析
    基于JQuery可拖动列表格插件DataTables的踩坑记
  • 原文地址:https://www.cnblogs.com/y7070/p/4973344.html
Copyright © 2011-2022 走看看