问题描述:row*col的矩阵表示一块田地,上面的'W'代表积水,'.'表示干地,问这块田地里面的积水能汇聚成几片水洼
我的动态规划解法:
子问题:前K个元素形成的水洼数
递推关系:对于第K个元素,考虑其左,左上,上,右上四个方向的元素,如果只存在一个水洼则将第K个元素加入此水洼,如果存在2个水洼,则只能是左方和右上方(因为左上方和上方的已经在子问题中解决),因为第K个元素,这两个水洼会合并(dele变量记录合并了多少次)
AC后去网上搜了搜解法,发现大神们直接用图的深度优先遍历解决了,而且时间、内存更少。好吧(在网上看的帖子将此题分为了动态规划类,直接去想子问题,没想到去与图的遍历联系(而且想到了递归,但是不想用递归),所以就直接DP解决了。下面先给出大神的代码,在给出我的代码。
大神的代码:192K 0ms
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> using namespace std; #define maxn 106 struct XPoint { int x; int y; XPoint(int xx, int yy) : x(xx), y(yy) { } XPoint() { } }; int n, m; bool map[maxn][maxn]; bool vis[maxn][maxn]; int ans; int dir[8][2] = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } }; bool ok(int x, int y) { if (x < 0 || y < 0 || x >= n || y >= m) return false; if (vis[x][y]) return false; return map[x][y]; } void work(int x, int y) { ans++; queue<XPoint> q; q.push(XPoint(x, y)); vis[x][y] = true; while (!q.empty()) { XPoint temp = q.front(); q.pop(); for (int i = 0; i < 8; i++) if (ok(temp.x + dir[i][0], temp.y + dir[i][1])) { vis[temp.x + dir[i][0]][temp.y + dir[i][1]] = true; q.push(XPoint(temp.x + dir[i][0], temp.y + dir[i][1])); } } } int main() { //freopen("t.txt", "r", stdin); scanf("%d%d", &n, &m); memset(map, 0, sizeof(map)); memset(vis, 0, sizeof(vis)); ans = 0; getchar(); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { char ch; scanf("%c", &ch); if (ch == 'W') map[i][j] = true; } getchar(); } for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) if (!vis[i][j] && map[i][j]) work(i, j); printf("%d\n", ans); return 0; }
#include <iostream>
#include <string>
using namespace std;
struct element
{
bool water;
int row;
int col;
int id;
};
void update_pondid(int row, int col, element ** arr,int arrrow, int arrcol,int oldid,int newid)
{
int i;
int j;
for ( i = 0; i <= row; i++ )
{
for ( j = 0; j < arrcol; j++ )
{
if(arr[i][j].id == oldid )
arr[i][j].id = newid;
}
}
}
void Around_Judge(int row, int col, element ** arr,int arrrow, int arrcol,int *pondcount,int * ponddelete)
{
if(arr[row][col].water)
{
int l = -1, rt = -1;
int id = -1;
bool re = false;
if( (col - 1) >= 0 && arr[row][col-1].water )
{
id = l = arr[row][col-1].id;
re = true;
}
if( (col - 1) >= 0 && (row - 1) >= 0 && arr[row-1][col-1].water )
{
id = arr[row-1][col-1].id;
re = true;
}
if( (row - 1) >= 0 && arr[row-1][col].water )
{
id = arr[row-1][col].id;
re = true;
}
if( (col + 1) < arrcol && (row - 1) >= 0 && arr[row-1][col+1].water)
{
rt = arr[row-1][col+1].id;
re = true;
}
if(!re)
{
*pondcount +=1;
arr[row][col].id = *pondcount;
}
else if( id != -1 && rt != -1 && id != rt )
{
arr[row][col].id = id;
update_pondid(row, col, arr,arrrow,arrcol,rt,id);
*ponddelete +=1;
}
else
{
id > rt ? arr[row][col].id = id: arr[row][col].id = rt;
}
}
}
int main()
{
int r = 0 , c = 0 ;
cin>>r>>c;
element **arr = new element*[r];
for(int i = 0; i < r; i++ )
arr[i] = new element[c];
//初始化
int i;
int j;
for ( i = 0; i < r; i++ )
{
for ( j = 0; j < c; j++ )
{
char t;
cin>>t;
element ele = {false,i,j,0};
if( t == 'W' )
ele.water = true;
arr[i][j] = ele;
}
}
int * count = new int;
*count = 1;
int * dele = new int;
*dele = 1;
for ( i = 0; i < r; i++ )
{
for ( j = 0; j < c; j++ )
{
Around_Judge(i,j,arr,r,c,count,dele);
}
}
cout<<(*count) - (*dele) <<endl;
return 0;
}