NOIP2010-2015後四題彙總

一、前言算法

  正式開始的第一週的任務——把NOIP2010至NOIP2015的全部D1/2的T2/3寫出暴力。共22題。數組

  暴力顧名思義,用簡單粗暴的方式解題,不以正常的思路思考。可以較好的保證正確性,可是最大的問題在於效率。搞OI這麼久,每次考試也常常糾結於暴力與正解之間,其實這二者概念上原本就沒有明顯的界限,是一組相對概念。網絡

  下面儘量的不提到正解,可是若是正解容易到我都可以輕鬆秒的話就仍是說一下了。優化

  普通的DFS/BFS搜索是暴力,但暴力不侷限於此。根據向總的話,記憶化搜索亦屬於暴力,名字逼格這麼高分數確定也高一些。什麼是記憶化搜索呢?ui

  記憶化搜索就是把咱們以前搜索過的狀態保存下來,在以後搜索再遇到這種狀態時就能夠避免重複搜索,直接調用上次搜索的結果便可。記憶化搜索適用於重複子結構較多的題目。spa

  這樣看上去貌似好熟悉。。。是啊很像動態規劃。。。ssr

  我姑且把它理解爲以DFS的形式來實現的動態規劃吧,,,雖然向總始終說他不是動態規劃。code

 

Tips:(我寫的/暴力最佳方式/正解)blog

 

二、NOIP2010排序

② tourist 烏龜棋(?/記憶化搜索/動態規劃)

思路:30分暴力直接強行DFS跑全部狀況很少說了。考慮本題有一個特別的地方——重疊子結構不少,常常可能出現使用卡片個數相同可是順序不一樣的狀況。若是直接DFS的話,會浪費大量時間。因爲總狀態比較少,4張卡片每張只有至多40張,故能夠把全部狀態存入一個四維數組,f[a][b][c][d]表示在剩下a張1,b張2,c張3,d張4時能夠得到的最大分數。在DFS時若是遇到以前已經遇到過的狀態,進行比對,選取較大值轉移。這樣能夠省去大量時間,也就是所謂的記憶化搜索。然而一旦你把f[a][b][c][d]的狀態轉移方程寫出來就會發現。。和動態規劃有什麼區別呢。

代碼:

#include <cstdio>
#include <cstring>
#define MAXN 355
#define MAXM 45

int n, m, w[MAXN], x, t[5], f[MAXM][MAXM][MAXM][MAXM];

int max(int a, int b) {
    return a > b ? a : b;
}

int DFS(int o, int a, int b, int c, int d) {
    if (f[a][b][c][d] != -1) return f[a][b][c][d]; 
    f[a][b][c][d] = 0;
    if (a) f[a][b][c][d] = max(DFS(o + 1, a - 1, b, c, d), f[a][b][c][d]);
    if (b) f[a][b][c][d] = max(DFS(o + 2, a, b - 1, c, d), f[a][b][c][d]);
    if (c) f[a][b][c][d] = max(DFS(o + 3, a, b, c - 1, d), f[a][b][c][d]);
    if (d) f[a][b][c][d] = max(DFS(o + 4, a, b, c, d - 1), f[a][b][c][d]);
    f[a][b][c][d] += w[o];
    return f[a][b][c][d];
}

int main() {
    freopen("tortoise.in", "r", stdin);
    freopen("tortoise.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
    for (int i = 1; i <= m; i++) scanf("%d", &x), t[x]++;
    memset(f, -1, sizeof(f));
    printf("%d", DFS(1, t[1], t[2], t[3], t[4]));
    return 0;
}

 

④ water 引水入城(?/BFS+枚舉/BFS+動態規劃)

思路:對於30分,題目明確是不能知足要求。。(我居然沒意識到這個的重要性) 

 

三、NOIP2011

② hotel 選擇客棧(動態規劃/枚舉+前綴和/搜索+優化??)

代碼:

#include <cstdio>
#define MAXN 200005
#define MAXK 65

int n, k, p, s, c, v, a[MAXN], f[MAXK][MAXN];

int main() {
    freopen("hotel.in", "r", stdin);
    freopen("hotel.out", "w", stdout);
    scanf("%d %d %d", &n, &k, &p);
    for (int i = 1; i <= n; i++) {
        scanf("%d %d", &c, &v);
        for (int j = 0; j < k; j++) f[j][i] = f[j][i - 1] + (j == c);
        s += (v <= p ? f[c][a[i] = i] - 1 : f[c][a[i] = a[i - 1]]);
    }
    printf("%d\n", s);
    return 0;
}

 

③ mayan Mayan遊戲(搜索/搜索/搜索)

思路:太長不寫。噁心死了。

 

⑤ qc 聰明的質檢員(?/二分答案/二分答案)

思路:

代碼:

 

⑥ bus 觀光公交(?/最短路/貪心或網絡流)

思路:

代碼:

 

四、NOIP2012

② game 國王遊戲(貪心/貪心/貪心)

思路:這個貪心究竟是如何證實的仍是不清楚啊,之前作過因此知道怎麼貪心。可是我仍是耿直的寫了直接根據一隻手來貪心50分。感受題目好鬼。對了記得寫高精度。

50分代碼:

#include <cstdio>
#include <algorithm>
using namespace std;

#define MAXN 1005

typedef long long ll;

#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif

ll n, x0, y0, o, ans;

struct Mst {
    ll x, y;
} a[MAXN];

struct Cmp {
    bool operator () (Mst a, Mst b) {
        return a.y < b.y;
    }
} x;

int main() {
    freopen("game.in", "r", stdin);
    freopen("game.out", "w", stdout);
    scanf(lld lld lld, &n, &x0, &y0), o = x0;
    for (int i = 1; i <= n; i++) scanf(lld lld, &a[i].x, &a[i].y);
    sort(a + 1, a + n + 1, x);
    for (int i = 1; i <= n; i++) ans = max(ans, o / a[i].y), o *= a[i].x;
    printf(lld, ans);
    return 0;
}

 

③ drive 開車旅行(?/枚舉/倍增+set)

思路:就枚舉吧。

 

⑤ classroom 借教室(線段樹/線段樹/二分答案+差分)

思路:30分模擬。能夠很明顯的看出來線段樹是很適合這道題的,只要常數不是很大,100分到手(我也不知道怎麼纔會把常數寫大)。

代碼:

#include <cstdio>
#define MAXN 1000005

int n, m, c[MAXN], d[MAXN], x[MAXN], y[MAXN], get;

struct Tree {
    int v, f;
} t[MAXN * 4];

int min(int a, int b) {
    return a < b ? a : b;
}

void build(int o, int l, int r) {
    if (l == r) {
        t[o].v = c[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(o << 1, l, mid), build(o << 1 | 1, mid + 1, r);
    t[o].v = min(t[o << 1].v, t[o << 1 | 1].v);
}

void pushDown(int o) {
    t[o << 1].v -= t[o].f, t[o << 1 | 1].v -= t[o].f;
    t[o << 1].f += t[o].f, t[o << 1 | 1].f += t[o].f;
    t[o].f = 0;
}

void dec(int o, int l, int r, int ql, int qr, int v) {
    if (get) return;
    if (t[o].f) pushDown(o);
    if (l == ql && r == qr) {
        t[o].v -= v, t[o].f += v;
        if (t[o].v < 0) get = 1;
        return;
    }
    int mid = (l + r) >> 1;
    if (qr <= mid) dec(o << 1, l, mid, ql, qr, v);
    else if (ql >= mid + 1) dec(o << 1 | 1, mid + 1, r, ql, qr, v);
    else dec(o << 1, l, mid, ql, mid, v), dec(o << 1 | 1, mid + 1, r, mid + 1, qr, v);
    t[o].v = min(t[o << 1].v, t[o << 1 | 1].v);
}

int main() {
    freopen("classroom.in", "r", stdin);
    freopen("classroom.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
    build(1, 1, n);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &d[i], &x[i], &y[i]);
        dec(1, 1, n, x[i], y[i], d[i]);
        if (get) {
            printf("-1\n%d", i);
            return 0;
        }
    }
    printf("0");
    return 0;
}

 

 

⑥ blockade 疫情控制(枚舉/枚舉/二分答案+貪心+倍增)

思路:20分枚舉。

代碼:

#include <cstdio>
#include <algorithm>
using namespace std;

#define MAXN 10005

int n, u, v, w, m, a[MAXN];
int o, h[MAXN], vis[MAXN], res, b[MAXN], c[MAXN], btot, ctot;

struct Edge {
    int v, next, w;
} e[MAXN];

void addEdge(int u, int v, int w) {
    o++, e[o] = (Edge) {v, h[u], w}, h[u] = o;
}

void DFS(int o, int fa) {
    for (int x = h[o]; x; x = e[x].next) {
        int v = e[x].v;
        if (v == fa) continue;
        if (a[v]) res += a[v];
        DFS(v, o);
    }
}

int work() {
    for (int x = h[1]; x; x = e[x].next) {
        int v = e[x].v;
        res = a[v], DFS(v, 1);
        if (!res) b[++btot] = e[x].w; 
        else if (res != 1) c[++ctot] = e[x].w * (res - 1);
    }
    sort(b + 1, b + btot + 1), sort(c + 1, c + ctot + 1);
    return b[1] + c[ctot];
}



int main() {
    freopen("blockade.in", "r", stdin);
    freopen("blockade.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n - 1; i++)
        scanf("%d %d %d", &u, &v, &w), addEdge(u, v, w), addEdge(v, u, w);
    scanf("%d", &m);
    for (int i = 1; i <= m; i++) scanf("%d", &o), a[o]++;
    printf("%d", work());
    return 0;
}

 

五、NOIP2013

② match 火柴排隊(樹狀數組+逆序對/枚舉/樹狀數組或歸併排序+逆序對)

思路:考慮給出的式子在什麼狀況下能夠得到最小值?兩列數組分別最大對最大,次大對次大……最小對最小。爲了達到這一局面,求逆序對就好了!(就好了。哦。)這個點確實考的很是偏啊,若是沒有提早看過的話怎麼作?

這個插下逆序對的概念:

對於一個包含N個非負整數的數組A[1..n],若是有i < j,且A[i] > A[j],則稱(A[i] , A[j])爲數組A中的一個逆序對。

代碼:

#include <cstdio>
#include <algorithm>

#define MAXN 100005
#define MOD 99999997
using namespace std;

int n, a[MAXN], b[MAXN], ta[MAXN], tb[MAXN], c[MAXN], ans, tot[MAXN];

struct cmpa {
    bool operator () (int a,int b) {
        return (ta[a]<ta[b]);
    }
} xa;

struct cmpb {
    bool operator () (int a, int b) {
        return (tb[a] < tb[b]);
    }
} xb;

int lowbit(int o) { 
    return o & -o; 
}

void update(int o) {
    while (o <= n) tot[o]++, o += lowbit(o);
}

int getSum(int o) {
    int ans = 0;
    while (o) ans += tot[o], o -= lowbit(o);
    return ans;
}
 
int main() {
    freopen("match.in", "r", stdin);
    freopen("match.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &ta[i]), a[i] = i;
    for (int i = 1; i <= n; i++) scanf("%d", &tb[i]), b[i] = i;
    sort(a + 1, a + n + 1, xa), sort(b + 1, b + n + 1, xb);
    for (int i = 1; i <= n; i++) c[b[i]] = a[i];
    for (int i = 1; i <= n; i++) update(c[i]), (ans += (i - getSum(c[i]))) %= MOD;
    printf("%d", ans);
    return 0;
}

 

③ truck 貨車運輸(最大生成樹/SPFA+優化/最大生成樹+倍增)

思路:30分算法直接SPFA維護最長路,我用的30分是Kruskal維護最大生成樹,一條邊一條邊加進去進行判斷。。。然而這道題作到60分的暴力也不難——就是把這兩種30分算法綜合一下(what...)。當且僅當所選擇的邊在最大生成樹上的時候,能夠獲得最優解。故能夠事先求出最大生成樹,在最大生成樹上進行SPFA!蠢的想不到啊臥槽。100分的話,感受不是很難吧暫時沒寫,最大生成樹+樹上倍增LCA。

30分代碼:

#include <cstdio>
#include <algorithm>

#define MAXN 10005
#define MAXM 50005
#define INF 1 << 30

using namespace std;

int n, u, v, w, q, o; 
int s, t, set[MAXN], m;

struct Edge {
    int u, v, w;
};

Edge e[MAXN * 2];

struct Cmp {
    bool operator () (Edge a, Edge b) {
        return (a.w > b.w);
    }
} x;

void addEdge(int u, int v, int w) {
    o++, e[o] = (Edge) {u, v, w};
}

int check(int x) {
    return (set[x] == x ? x : set[x] = check(set[x]));
} 

int work() {
    int ans, get = 0;
    for (int i = 1; i <= m; i++) {
        if (check(s) == check(t)) {
            get = 1; 
            break; 
        }
        int c1 = check(e[i].u), c2 = check(e[i].v);
        if (c1 != c2) set[c1] = c2, ans = e[i].w;
    }
    return get ? ans : -1;
}

int main() {
    freopen("truck.in", "r", stdin);
    freopen("truck.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) scanf("%d %d %d", &u, &v, &w), addEdge(u, v, w);
    sort(e + 1, e + m + 1, x);
    scanf("%d", &q);
    while (q--) {
        scanf("%d %d", &s, &t);
        for (int i = 1; i <= n; i++) set[i] = i;
        printf("%d\n", work());
    }
    return 0;
}

 

60分代碼:

#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;

#define MAXN 10005
#define MAXM 50005
#define INF 1 << 30

struct Tmp {
    int u, v, w;
} te[MAXM];


struct Edge {
    int v, next, w;
} e[MAXN];

struct Cmp {
    bool operator () (Tmp a, Tmp b) {
        return a.w > b.w;
    }
} x;

int n, m, t, u, v, w, o, head[MAXN], vis[MAXN], dis[MAXN], q[MAXN * 2], set[MAXN];

int check(int o) {
    return o == set[o] ? o : set[o] = check(set[o]);
}

void addEdge(int u, int v, int w) {
    o++, e[o] = (Edge) {v, head[u], w}, head[u] = o;
}

int SPFA(int x, int y) {
    int h = 1, t = 2;
    memset(vis, 0, sizeof(vis)), memset(dis, -1, sizeof(dis));
    q[1] = x, vis[x] = 1, dis[x] = INF;
    while (h != t) {
        int o = q[h];
        for (int x = head[o]; x; x = e[x].next) {
            int v = e[x].v;
            if (dis[v] < min(dis[o], e[x].w)) {
                dis[v] = min(dis[o], e[x].w);
                if (!vis[v]) vis[v] = 1, q[t] = v, t++;    
            }
        }
        vis[o] = 0, h++;
    }
    return dis[y];
}

int main() {
    freopen("truck.in", "r", stdin);
    freopen("truck.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &u, &v, &w);
        te[i] = (Tmp) {u, v, w};
    }
    sort(te + 1, te + m + 1, x);
    for (int i = 1; i <= n; i++) set[i] = i;
    for (int i = 1; i <= m; i++) {
        int u = te[i].u, v = te[i].v, w = te[i].w;
        int c1 = check(u), c2 = check(v);
        if (c1 != c2) set[c1] = c2, addEdge(u, v, w), addEdge(v, u, w);
    }
    scanf("%d", &t);
    for (int i = 1; i <= t; i++) scanf("%d %d", &u, &v), printf("%d\n", SPFA(u, v));
    return 0;
}

 

⑤ flower 花匠(貪心/貪心/動態規劃+優化)

思路:最想吐槽的一道題,。爲何正解會想到動態規劃。。不是說不可作,這擺明了的能夠貪心啊!雖然兩年前甚至是一年前都沒法很快的想到,可是一年以後的我把這道題當作新題再看一次的時候,實在是想不通爲何要去動態規劃的路線。。因此我寫了一個代碼量極短的貪心。

代碼:

#include <cstdio>
#define MAXN 100005

int n, h[MAXN], t[2], o;

int max(int a, int b) {
    return a > b ? a : b;
}

int main() {
    freopen("flower.in", "r", stdin);
    freopen("flower.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &h[i]);
    for (int j = 0; j <= 1; j++, o = j)
        for (int i = 2; i <= n; i++)
            if (o ? (h[i] > h[i - 1]) : (h[i] < h[i - 1])) o ^= 1, t[o]++;
    printf("%d", max(t[0], t[1]) + 1);
    return 0;
}

 

⑥ puzzle 華容道(BFS+少許優化?/BFS/BFS+SPFA)

思路:直接寫了BFS,聽說是60分,可是最後得了70分。

70分代碼:

#include <cstdio>
#include <cstring>
#define MAXN 35

const int vx[4] = {0, 0, 1, -1}, vy[4] = {1, -1, 0, 0};

int n, m, t, a[MAXN][MAXN], vis[MAXN][MAXN][MAXN][MAXN];
int ex, ey, sx, sy, tx, ty;

struct Queue {
    int x, y, ox, oy, d;
} q[MAXN * MAXN * MAXN * MAXN];

int BFS() {
    int h = 1, t = 2;
    q[1] = (Queue) {ex, ey, sx, sy, 0};
    while (h != t) {
        for (int i = 0; i <= 3; i++) {
            int nx = q[h].x + vx[i], ny = q[h].y + vy[i];
            if (nx == q[h].ox && ny == q[h].oy) {
                q[t].ox = q[h].x, q[t].oy = q[h].y;
                if (q[t].ox == tx && q[t].oy == ty) return q[h].d + 1;
            }
            else q[t].ox = q[h].ox, q[t].oy = q[h].oy;
            if (!a[nx][ny] || vis[nx][ny][q[t].ox][q[t].oy]) continue;
            vis[nx][ny][q[t].ox][q[t].oy] = 1;
            q[t].x = nx, q[t].y = ny, q[t].d = q[h].d + 1;
            t++;
        }
        h++;
    }
    return -1;
}

int main() {
    freopen("puzzle.in", "r", stdin);
    freopen("puzzle.out", "w", stdout);
    scanf("%d %d %d", &n, &m, &t);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]);
    for (int i = 1; i <= t; i++) {
        memset(vis, 0, sizeof(vis));
        scanf("%d %d %d %d %d %d", &ex, &ey, &sx, &sy, &tx, &ty);
        vis[ex][ey][sx][sy] = 1;
        printf("%d\n", sx == tx && sy == ty ? 0 :BFS());
    }
    return 0;
}

 

 

六、NOIP2014

② link 聯合權值(BFS/BFS/樹形動態規劃)

思路:如今來看仍是NOIP2014的題最良心。。。直接根據點與點之間的關係找出全部距離爲2的點對,最後再統計權值便可。記得開long long。

代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXN 200005
#define MOD 10007

#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif

typedef long long ll;

ll h[MAXN], w[MAXN], tot[MAXN], n, u, v, o, ans, maxv;

struct edge {
    ll v, next;
} e[MAXN * 2];

void add(ll u, ll v) {
    o++, e[o] = (edge) {v, h[u]}, h[u] = o; 
}

void work(ll x, ll fa) {
    ll sonv = 0, tmax = 0, vmax;
    for (ll o = h[x]; o; o = e[o].next) {
        ll v = e[o].v;
        sonv += w[v];
        if (tmax < w[v]) tmax = w[v], vmax = v; 
    }
    for (ll o = h[x]; o; o = e[o].next) {
        ll v = e[o].v;
        if (v == fa) continue;
        if (v != vmax) maxv = max(maxv, tmax * w[v]);
        tot[v] += w[fa] + sonv - w[v], work(v, x);
        maxv = max(maxv, w[v] * w[fa]);
    }
}

int main() {
    freopen("link.in", "r", stdin);
    freopen("link.out", "w", stdout);
    scanf(lld, &n);
    for (ll i = 1; i < n; i++) scanf(lld " " lld, &u, &v), add(u, v), add(v, u);
    for (ll i = 1; i <= n; i++) scanf(lld, &w[i]);
    work(1, 0);
    for (ll i = 1; i <= n; i++) (ans += w[i] * tot[i]) %= MOD;
    printf(lld " " lld, maxv, ans);
    return 0;
}

 

③ bird 飛揚的小鳥(動態規劃/記憶化搜索/動態規劃)

思路:這個題搜索分高的有點過度啊(固然我也是受益者之一)。其實題目自己沒有太多難度,不管是搜索仍是記憶化搜索仍是動態規劃,最要注意的部分就是上界的特判。

代碼:

#include <cstdio>

#define MAXN 10005
#define MAXM 1005
#define INF 0x3f3f3f3f

int n, m, k, x[MAXN], y[MAXN], u[MAXN], d[MAXN], f[MAXN][MAXM], ans = INF, cnt;

int min(int a, int b) {
    return a < b ? a : b;
}

int main() {
    freopen("bird.in", "r", stdin);
    freopen("bird.out", "w", stdout);
    scanf("%d %d %d", &n, &m, &k);
    for (int i = 0; i < n; i++) scanf("%d %d", &x[i], &y[i]);
    for (int i = 0; i <= n; i++) u[i] = m + 1;
    for (int i = 1; i <= k; i++) {
        int o;
        scanf("%d", &o), scanf("%d %d", &d[o], &u[o]);
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] = INF;
            if (j > x[i - 1]) f[i][j] = min(f[i][j], min(f[i - 1][j - x[i - 1]], f[i][j - x[i - 1]]) + 1);
        }
        for (int j = m - x[i - 1]; j <= m; j++) f[i][m] = min(f[i][m], min(f[i - 1][j], f[i][j]) + 1);
        for (int j = d[i] + 1; j <= u[i] - 1; j++)
            if (j + y[i - 1] <= m) f[i][j] = min(f[i][j], f[i - 1][j + y[i - 1]]);
        for (int j = 1; j <= d[i]; j++) f[i][j] = INF;
        for (int j = u[i]; j <= m; j++) f[i][j] = INF;
        int get = 0;
        for (int j = 1; j <= m ; j++)
            if (f[i][j] != INF) {
                get = 1;
                break;
            }
        if (!get) {
            printf("0\n%d", cnt);
            return 0;
        }
        else if (u[i] != m + 1) cnt++;
    }
    for (int i = 1; i <= m; i++) ans = min(ans, f[n][i]);
    printf("1\n%d", ans);
    return 0;
}

 

⑤ road 尋找道路(搜索/搜索/搜索)

思路:來自day2的水題。正序逆序各對圖進行一次掃描,用DFS/BFS/SPFA都可。

代碼:

#include <cstdio>
#include <cstring>

#define MAXN 10005
#define MAXM 200005
#define INF 0x3f3f3f3f

int n, m, u, v, st, en, head[2][MAXN], o[2], dep[MAXN], vis[MAXN];

struct edge {
    int v, next;
} e[2][MAXM];

void add(int u, int v, int x) {
    o[x]++, e[x][o[x]] = (edge) {v, head[x][u]}, head[x][u] = o[x];
}

void init() {
    freopen("road.in", "r", stdin);
    freopen("road.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) scanf("%d %d", &u, &v), add(u, v, 0), add(v, u, 1);
    scanf("%d %d", &st, &en);
    memset(dep, INF, sizeof(dep));
}

void BFS1() {
    int q[MAXN], h = 1, t = 2;
    q[1] = en, vis[en] = 1;
    while (h != t) {
        int o = q[h];
        for (int x = head[1][o]; x; x = e[1][x].next) {
            int v = e[1][x].v;
            if (vis[v]) continue;
            vis[v] = 1, q[t] = v, t++;
        }
        h++;
    }
}

void BFS2() {
    int q[MAXN], h = 1, t = 2;
    q[1] = st, dep[st] = 0;
    while (h != t) {
        int o = q[h], no = 0;
        for (int x = head[0][o]; x; x = e[0][x].next) {
            int v = e[0][x].v;
            if (!vis[v]) { 
                no = 1; 
                break; 
            }
        }
        if (!no)
            for (int x = head[0][o]; x; x = e[0][x].next) {
                int v = e[0][x].v;
                if (dep[v] > dep[q[h]] + 1) q[t] = v, t++, dep[v] = dep[q[h]] + 1;
            }
        h++;
    }
}

int main() {
    init(), BFS1(), BFS2();
    if (dep[en] != INF) printf("%d", dep[en]); else printf("-1");
    return 0;
}

 

⑥ equation 解方程(搜索/搜索/搜索+Hash+取模)

思路:30分從頭搜到尾。。。50分是高精度吧,沒時間寫就沒有寫了。聽說搜索+取模能夠省去高精度直接AC?如今應該不是研究這個的時候了。。。我只寫了30分的。

30分代碼:

#include <cstdio>
#define MAXN 105

int n, m, a[MAXN], tot = 0, ans[MAXN];

int main() {
    freopen("equation.in", "r", stdin);
    freopen("equation.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 0; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i <= m; i++) {
        int x = 1, o = 0;
        for (int j = 0; j <= n; j++) o += a[j] * x, x *= i;
        if (o == 0) ans[tot++] = i;
    }
    printf("%d\n", tot);
    for (int i = 0; i < tot; i++) printf("%d\n", ans[i]);
    return 0;
}    

 

七、NOIP2015

呵呵噠。你敢信我對這一年的題目什麼印象都沒有。。他們在那裏講信息傳遞的時候我一臉懵逼。確實一點都不想回憶這個,因此15年的我一道題都沒有去作。

② message 信息傳遞

③ landlords 鬥地主

⑤ substring 子串

⑥ transport 運輸計劃

相關文章
相關標籤/搜索