UVa 10599 Robots(II)(LIS变种)

题意:

给出一个矩阵的长和宽n,m,然后输入一些坐标,表示那个坐标上有垃圾(这道题里面每个坐标只有一个垃圾),然后机器人从(1,1)开始运动终点是(n,m)

运动的方向只能是向下或者向右走,途中它要捡垃圾,目的是要令它捡的垃圾数最多,然后在能保证捡到的垃圾数最多的情况下,统计出有多少种方法,然后输出其中任意的一种方案。

思路:

可以把带垃圾的格子处理成一个sequence,然后求其LIS,只不过多了一层限制,就是机器人必须往斜下方向走罢了。

中间涉及到到达终点的路径数以及打印路径。

1. dp[i] == dp[j] + 1 : num[i] += num[j],

2. dp[i] < dp[i] + 1 : num[i] = num[j].

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

const int MAXN = 110;
const int MAXD = 10010;
bool g[MAXN][MAXN];
int n, seq[MAXD], dp[MAXD], pre[MAXD], num[MAXD];
int row, col;

void solve()
{
    n = 0;
    for (int i = 1; i <= row; ++i)
        for (int j = 1; j <= col; ++j)
            if (g[i][j])
                seq[n++] = (i - 1) * col + j - 1;

    if (seq[n-1] != col * row - 1)
        seq[n++] = row * col - 1;

    memset(pre, -1, sizeof(pre));
    for (int i = 0; i < n; ++i)
    {
        dp[i] = 1, num[i] = 1;

        for (int j = 0; j < i; ++j)
            if ((seq[i]%col) >= (seq[j]%col))
            {
                if (dp[i] < dp[j] + 1)
                    dp[i] = dp[j] + 1,
                    num[i] = num[j],
                    pre[i] = j;
                else if (dp[i] == dp[j] + 1)
                    num[i] += num[j];
            }
    }        
    if (!g[row][col])
        --dp[n-1];
}

void outpath(int u)
{
    if (pre[u] != -1)
        outpath(pre[u]);
    if (u != n - 1 || g[row][col])
        printf(" %d", seq[u] + 1);
}

int main()
{
    int cases = 0;
    while (scanf("%d %d", &row, &col))
    {
        if (row == -1 && col == -1) 
            break;

        int x, y;
        memset(g, false, sizeof(g));
        while (scanf("%d %d", &x, &y) && x && y)
            g[x][y] = true;

        solve();

        printf("CASE#%d: %d %d", ++cases, dp[n-1], num[n-1]);
        outpath(n - 1);
        printf("\n");
    }
    return 0;
}

 

posted @ 2012-11-26 14:44  kedebug  阅读(605)  评论(0编辑  收藏  举报