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; }
相关文章推荐
- Android中BindService方式使用的理解
- BZOJ 1088 扫雷Mine
- Java多线程<1>
- 第二百零六天 how can I 坚持
- c中的游戏——猜数字
- [TYVJ 1927] 『Citric II』一道防AK好题 · 模拟
- Win32-2048游戏
- 优秀程序员的好习惯,提高效率
- UILabel边框效果
- Android学习【10】PreferenceFragment偏好设置(二)
- Git使用小结(一)
- JVM调优总结 -Xms -Xmx -Xmn -Xss
- C++静态计算的例子
- Mountain Road
- 【程序员眼中的统计学(12)】相关与回归:我的线条如何?
- 第一发博客
- Linux重定向的系统调用方法
- 【知识点整理(java)】Java Thread简单使用注意点汇总(四)
- linux 下C编程(七) 之 杂杂的程序
- MariaDB基础(1)--数据类型