UVa 10599 - Robots(II)
传送门
题意
一个机器人要打扫垃圾,只能左、下走,求他最多能扫几个垃圾,路线有几条,选择一条输出。
思路
$dp[i][j]$表示该点开始能打扫的最多垃圾。
然后记忆化搜索就行。
至于统计路线数目,也是用记忆化搜索,到最后一个垃圾时候返回1即可。
输出路线,只要满足某处有垃圾并且那点比当前点的垃圾数少1就行。
代码
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MAXN = 100 + 10;
const int INF = 2147483647;
int mp[MAXN][MAXN], dp[MAXN][MAXN], cnt, r, c, way[MAXN][MAXN];
int cal(int x, int y)
{
int &cur = way[x][y];
if (cur != -1)
return cur;
if (dp[x][y] == 1)
return cur = 1;
cur = 0;
for (int i = x; i <= r; i++)
for (int j = y; j <= c; j++)
if (mp[i][j] && dp[i][j] + mp[x][y]== dp[x][y])
cur += cal(i, j);
return cur;
}
int DFS(int x, int y)
{
int &cur = dp[x][y];
if (cur != -1)
return cur;
if (x == r && y == c)
return cur = mp[r][c];
cur = 0;
if (x + 1 <= r)
cur = max(DFS(x + 1, y) + mp[x][y], cur);
if (y + 1 <= c)
cur = max(DFS(x, y + 1) + mp[x][y], cur);
return cur;
}
void PrintAns(int x, int y)
{
if (dp[x][y] == 1)
if (mp[x][y])
{
printf(" %d\n", (x - 1) * c + y);
return;
}
printf(" %d", (x - 1) * c + y);
for (int i = x; i <= r; i++)
for (int j = y; j <= c; j++)
if (mp[i][j] && dp[x][y] - 1 == dp[i][j])
{
PrintAns(i, j);
return;
}
}
void OutPut()
{
for (int i = 1; i <= r; i++)
for (int j = 1; j <= c; j++)
if (mp[i][j] && dp[i][j] == DFS(1, 1))
{
PrintAns(i, j);
return;
}
}
int main()
{
//freopen("input.txt", "r", stdin);
int i, j, a, b, cases = 0;
while (scanf("%d%d", &r, &c), r + c != -2)
{
cnt = 0;
memset(mp, 0, sizeof mp);
memset(dp, -1, sizeof dp);
memset(way, -1, sizeof way);
while (scanf("%d%d", &a, &b), a + b)
mp[a][b] = 1;
int ans = DFS(1, 1);
cal(1, 1);
printf("CASE#%d: %d %d", ++cases, ans, way[1][1]);
OutPut();
}
return 0;
}