UVA10599 - Robots(II)(变形的LIS)

来源:互联网 发布:数据库收银员表怎么建 编辑:程序博客网 时间:2024/06/05 16:43

题意:一个机器人在n * m的网格里面捡垃圾,机器人只能向右或向下走,求出能捡到的垃圾数量的最大值,有多少条路径可以达到最大值,以及输出其中一条路径。


思路:按照题意可以看出,因为机器人只能向右和向下走,所以纵坐标就不重要的,而横坐标是递增的。当将所有拥有垃圾的格子经过计算得到它的一维值(唯一的),得到一组的数组。那就可以转化为求最长上升子序列。但这个LIS的条件是mod(m)要大于前一个。计算数量时,当d[i] = d[j] + 1时,就相当于以i为结束时的最长上升子序列比以j结束时的最长上升子序列大1,那么达到d[i]的路径的数量就为v[i] += v[j];同理当d[i] < d[j] + 1时,v[i] = v[j];至于路径的输出就使用记录数组,递归输出。

自己在初始化将图转化为数组WA了,后来看了别人的改了过来,但还是不懂为什么那样子不对。。。


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 10005;int g[105][105], d[MAXN], arr[MAXN], v[MAXN], path[MAXN];int n, m, cnt;void init () {    memset(g, 0, sizeof(g));    int a, b;      cnt = 0;    while (scanf("%d %d", &a, &b) && a && b) {        g[a][b] = 1;          //arr[cnt++] = (a - 1) * m + b - 1;      }    for (int i = 1; i <= n; i++)        for (int j = 1; j <= m; j++)            if (g[i][j])                arr[cnt++] = (i - 1) * m + j - 1;    if (!g[n][m])        arr[cnt++] = n * m - 1;}void LIS() {    memset(path, -1, sizeof(path));    memset(v, 0, sizeof(v));    memset(d, 0, sizeof(d));    for (int i = 0; i < cnt; i++) {        d[i] = 1, v[i] = 1;        for (int j = 0; j < i; j++)            if (arr[i] % m >= arr[j] % m) {                if (d[i] < d[j] + 1) {                    d[i] = d[j] + 1;                     path[i] = j;                    v[i] = v[j];                }                else if (d[i] == d[j] + 1)                     v[i] += v[j];            }    }    if (!g[n][m])        d[cnt - 1]--;}void outPut(int u) {    if (path[u] != -1)        outPut(path[u]);    if (u != cnt - 1 || g[n][m])        printf(" %d", arr[u] + 1); }int main() {    int t = 1;    while (scanf("%d %d", &n, &m) != EOF) {        if (n == -1 && m == -1)             break;        init();        LIS();          printf("CASE#%d: %d %d", t++, d[cnt - 1], v[cnt - 1]);        outPut(cnt - 1);        printf("\n");    }    return 0;}


0 0