您的位置:首页 > 其它

uva 10599 - Robots(II) -动态规划

2015-10-25 21:58 239 查看
//
//  main.cpp
//  uva 10599 - Robots(II) --动态规划
/*
此题的状态转移方程好想,很简单。
d[i][j] = max(d[i+1][j] ,d[i][j+1]) + g[i][j]  ;
另外 求其中的一条路径也好写。
对于方案数,这是难点啊。MD,原来 即使行代码就解决的,价格方案数。。。。。
这里方案数,要注意的是注意重复,不能根据上面的地推方程来想。对于i行j列,如果(i+1,j) ,((i,j+1)都不存在垃圾,(i+1,j+1)存在垃圾,那么我们按照count[i][j] = count[i+1][j]  +count[i][j+1],就会重复的加上了count[i+1][j+1].
从g[i][j]出发 ,count[i][j] = sum(count[x][y]) ,其中d[x][y] + g[i][j]  = d[i][j].如果 (i,j)是最后一个垃圾, count[i][j] =1 (这是我wa的原因);这个地推方程也是很容易想到的。
但是如何找到下一个垃圾点呢?这个垃圾点得满足 从
(i, j ) 到(x,y)存在一条不包含垃圾的路径.这显然可以使用bfs就解决了。
到这里这道题就可以AC了。

*/
#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
#define ll long long
using namespace std ;
int d[110][110] ;
int g[110][110] ;
ll ways[110][110] ;
int n , m  ;
vector<int > path ;
struct node{
int x ,y  ;
node(int x , int y ):x(x) ,y(y){} ;
};
vector<node > touch[110][110] ;
int flag[110][110];
int dir[2][2] ={{0 , 1},{1,0}} ;
void bfs(int x,int y  )
{
memset(flag, 0, sizeof(flag)) ;
touch[x][y].clear() ;
queue<node> q ;
int tx = x, ty = y  ;
q.push(node(x , y )) ;
flag[x ][y] = 1 ;
while (!q.empty()) {
node  u = q.front() ; q.pop() ;
//        x = u.x ; y = u .y  ;
for (int i  = 0; i < 2; i++) {
x  = u.x + dir[i][0 ] ; y = u.y +  dir[i][1] ;
if(x <= n &&y <= m && !flag[x][y])
{
flag[x][y] =1 ;
if(g[x][y]){
touch[tx][ty].push_back(node(x,y) ) ;
//
//                    bfs(x, y) ;
continue ;
}
else{
q.push(node(x,y)) ;
}
}
}
}
}
ll getWays(int  x , int y)
{
if (ways[x][y] >=0) {
return ways[x][y] ;
}
if(x == n || y == m )
{
return ways[x][ y] = 1 ;
}
else{
ll ans = 0    ;
bfs(x, y) ;
int len = (int )touch[x][y].size() ;
for (int i = 0  ; i < len  ; i++) {
int x1 = touch[x][y][i].x ;
int y1 = touch[x][y][i].y ;
if(d[x][y] == g[x][y] + d[x1][y1])
{
ans += getWays(x1, y1) ;
}
}
if (ans == 0 ) {
ans = 1 ;
}
ways[x][y] = ans ;
return ans ;
}
}
void getPath(int x , int y)
{
if (g[x][y] == 1  ) {
path.push_back(x*m - m + y) ;
}
if (y<m && d[x][y] == g[x][y] + d[x][y+1]) {
getPath(x, y+1) ;
}
else if(x < n &&d[x][y] == g[x][y] + d[x+1][y])
{
getPath(x+1, y) ;
}
}
int main() {
int x,y,kase=0;
while (scanf("%d %d" ,&n,&m)==2 && n + m !=-2 ) {
memset(g, 0, sizeof(g)) ;
while (scanf("%d %d" ,&x,&y)==2&& x!= 0 && y!= 0 ) {
g[x][y] = 1 ;
}
memset(d, 0, sizeof(d)) ;
for (int i = m; i>0; i--) {
d
[i] = d
[i+1] +g
[i] ;
}
for (int i = n-1; i>0; i--) {
d[i][m] = d[i+1][m] + g[i][m] ;
for (int j = m-1 ; j>0; j--) {
d[i][j] = g[i][j] ;
d[i][j] += max(d[i][j+1] , d[i+1][j]) ;
}
}
printf("CASE#%d: %d" , ++kase,d[1][1]) ;
memset(ways, -1, sizeof(ways)) ;

printf(" %lld" , getWays(1, 1)) ;
path.clear() ;
getPath(1,1) ;
for (int i = 0 ; i < path.size(); i++) {
printf(" %d" ,path[i]) ;
}
cout << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: