UVA_10599
一开始我写的时候把一个点有多个垃圾的情况也考虑进去了,后来交了一下发现是不存在这种情况的。
这个题目由于只能往右走或者往下走,而且路线的不同是以垃圾的位置区分的,那么我们不妨转化成最长上升子序列的问题去处理。
最后为了能明确得出路线的条数,如果终点没有垃圾的话我们不妨把终点也加进去,只不过标记一下这里没有垃圾就可以了,在打印路径的时候不打印出这个点即可。
#include<stdio.h>
#include<string.h>
#define MAXN 110
#define MAXD 10010
int N, M, g[MAXN][MAXN], p[MAXD], f[MAXD], num[MAXD];
int s[MAXD], y[MAXD], d[MAXD];
void printpath(int st)
{
int i;
if(p[st] != -1)
printpath(p[st]);
for(i = 0; i < d[st]; i ++)
printf(" %d", s[st]);
}
void solve()
{
int i, j, k, n;
n = 0;
for(i = 1; i <= N; i ++)
for(j = 1; j <= M; j ++)
if(g[i][j])
{
s[n] = (i - 1) * M + j;
y[n] = j;
d[n] = g[i][j];
n ++;
}
if(s[n - 1] != N * M)
{
s[n] = N * M;
y[n] = M;
d[n] = 0;
n ++;
}
memset(f, 0, sizeof(f));
memset(p, -1, sizeof(p));
for(i = 0; i < n; i ++)
num[i] = 1;
for(i = 0; i < n; i ++)
{
for(j = 0; j < i; j ++)
if(y[j] <= y[i])
{
if(f[j] > f[i])
{
f[i] = f[j];
num[i] = num[j];
p[i] = j;
}
else if(f[j] == f[i])
num[i] += num[j];
}
f[i] += d[i];
}
printf("%d %d", f[n - 1], num[n - 1]);
printpath(n - 1);
printf("\n");
}
void init()
{
int i, j, x, y, t = 0;
for(;;)
{
scanf("%d%d", &N ,&M);
if(N == -1 && M == -1)
break;
memset(g, 0, sizeof(g));
for(;;)
{
scanf("%d%d", &x, &y);
if(!x && !y)
break;
g[x][y] ++;
}
printf("CASE#%d: ", ++ t);
solve();
}
}
int main()
{
init();
return 0;
}