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;
}
-------------------------------------------------------
kedebug
Department of Computer Science and Engineering,
Shanghai Jiao Tong University
E-mail: kedebug0@gmail.com
GitHub: http://github.com/kedebug
-------------------------------------------------------