首页 > 代码库 > uva 1444 - Knowledge for the masses(高效)

uva 1444 - Knowledge for the masses(高效)

题目链接:uva 1444 - Knowledge for the masses

题目大意:给出R和L,R表示有R行,L表示一行的最大长度。
对于每一行,给出n,然后是n个数,arr[i]为0表示空格,长度为1,否则表示书架,长度为arr[i]。现在人要从上边走到下边,问说最少移动几个书架,并且输出可以通过的路径坐标。

解题思路:c[i]表示第i个坐标有多少行可以通过,当c[i]==R时,表示人可以从该位置穿过整个书架。g[i]表示从i这个位置穿过的代价。然后对于每一行处理,pos[i]记录第i个空格的位置,vis[i]记录左移的代价,用来和右移代价作比较,取最小值。注意第二行输出的时候每个数后面都要根空格,否则PE。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 1e6+5;
const int INF = 0x3f3f3f3f;

int R, L, c[maxn], g[maxn];
int n, arr[maxn], pos[maxn], vis[maxn];

void  input () {
    scanf("%d", &n);
    memset(vis, -1, sizeof(vis));

    int cnt = 0, mv = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
        if (arr[i] == 0) {
            mv++;
            pos[cnt++] = i;
            c[mv-1]++;
        } else {
            int k = min(cnt, arr[i]);
            mv = mv + arr[i];
            for (int j = 1; j <= k; j++) {
                int u = mv - j;
                vis[u] = i - pos[cnt-j] - j + 1;
                g[u] += vis[u];
                c[u]++;
            }
        }
    }

    reverse(arr, arr+n);

    cnt = 0;
    for (int i = 0; i < n; i++) {
        if (arr[i] == 0) {
            mv--;
            pos[cnt++] = i;
        } else {
            int k = min(cnt, arr[i]);
            mv = mv - arr[i];
            for (int j = 0; j < k; j++) {
                int u = mv + j;
                if (vis[u] == -1) {
                    vis[u] = i - pos[cnt-j-1] - j;
                    g[u] += vis[u];
                    c[u]++;
                } else {
                    int tmp = i - pos[cnt-j-1] - j;
                    g[u] += min(0, tmp - vis[u]);
                }
            }
        }
    }
}

void init () {
    scanf("%d%d", &R, &L);
    memset(c, 0, sizeof(c));
    memset(g, 0, sizeof(g));

    for (int i = 0; i < R; i++)
        input();
}

void solve () {
    int ans = INF, cnt = 0;
    for (int i = 0; i < L; i++) {
        if (c[i] == R) {
            if (g[i] < ans) {
                cnt = 0;
                ans = g[i];
            }

            if (g[i] == ans)
                vis[cnt++] = i;
        }
    }

    /*
    printf("%d\n%d", ans, vis[0]);
    for (int i = 1; i < cnt; i++)
        printf(" %d", vis[i]);
    printf("\n");
    */
    printf("%d\n", ans);
    for (int i = 0; i < cnt; i++)
        printf("%d ", vis[i]);
    printf("\n");
}

int main () {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        init();
        solve();
    }
    return 0;
}

uva 1444 - Knowledge for the masses(高效)