#2 #8,为何数组要开到 1000 才能过

P1434 [SHOI2002] 滑雪

言琢დ @ 2024-01-05 13:08:03

RT

感觉按照题目要求的范围数组开得足够大了但还是过不掉,不清楚是什么原因。

#include<cstdio>
#include<cstring>
int init(){
    char c = getchar();
    int x = 0, f = 1;
    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-') f = -1;
    for (; c >= '0' && c <= '9'; c = getchar())
        x = (x << 1) + (x << 3) + (c ^ 48);
    return x * f;
}
void print(int x){
    if (x < 0) x = -x, putchar('-');
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
const int N = (int) 1e3 + 5; // 这里如果改成 1e2 + 5 就会有 2 个点 WA
int n, m, a[N][N], du[N * N], q[N * N];
struct Node{
    int next, to;
} s[N * N]; int head[N * N], sLen;
void add(int u, int v){
    s[++sLen].next = head[u];
    s[sLen].to = v;
    head[u] = sLen;
    ++du[v];
}
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};
bool ok(int x, int y){
    return x >= 1 && y >= 1 && x <= n && y <= m;
}
int node(int x, int y){
    return (x-1) * m + y;
}
int mx(int x, int y){
    return x > y ? x : y;
}
int dp[N * N];
int main(){
    n = init(), m = init();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            a[i][j] = init();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            for (int k = 0; k < 4; ++k) {
                int ni = i + dx[k], nj = j + dy[k];
                if (ok(ni, nj) && a[i][j] > a[ni][nj])
                    add(node(i, j), node(ni, nj));
            }
    for (int i = 1; i <= n * m; ++i)
        if (!du[i]) dp[q[++q[0]] = i] = 1;
    int nxt = 1, ans = 1;
    while (nxt <= q[0]) {
        int u = q[nxt++];
        for (int i = head[u]; i; i = s[i].next) {
            int v = s[i].to;
            ans = mx(ans, dp[v] = mx(dp[v], dp[u] + 1));
            if (!--du[v]) q[++q[0]] = v;
        }
    }
    print(ans), putchar('\n');
}

by 言琢დ @ 2024-01-05 13:09:08

怀疑可能是数组 q 开小了,因为经过 assert 发现 q[0] <= n * m 并不成立。

但我寻思着这种有向无环图按道理每个点只能进队一次吧,为啥不满足这个性质,不太懂哦


|