poj2056

来源:互联网 发布:数据库前置库 编辑:程序博客网 时间:2024/06/08 06:01

题目不难,但是要AC不容易。首先题目不好理解,其次就算理解了题意也感觉无法动手,要么纯暴力显然超时,主要是粗向转化的思想。将其转化为一般的搜索问题后,就是简单的广搜了(由于深搜层次太大,有将近200层,故用深搜求最小值显然没有广搜来的快,此题明显的可以知道广搜再求最值问题时的优势——可立即返回,而深搜则只能剪枝,通过比较来减少递归次数,但总体上来讲:广搜明显快于深搜,尤其但递归层次比较大时)。

分析如下:

大致题意为:给定一个矩阵,将该矩阵划分为三等分,从左到右(严格)分别为W、S、B。其中S将W和B分开,每个点最多总共有8个连接点:分别为上下、左右、左斜上、左斜下、右斜上、右斜下与其连接的点。那么分析后不难发现:要想用S将W和B分开,即W和B中的点两两均不相连,有题目中的要求:

1)S从矩形第一行开始,一直到矩形最后一行为止

2)S在每一行都只有三种方式转移:左、右、下 

也就是说:S从第一行到最后一行必定每一行都有元素,求所有这些元素应该可以顺次连接成一条线。

也即S必须为上下左右的顺次连接,即不存在倾斜的情况(或断点的情况)。

接着往下分析:S可以选择转移的范围

题目中已经说明了improment的策略:

1)将B中若干顶点移动到S中,这些顶点一定是左相连S中的某一顶点(注意是严格的左相连,就因为这个没有看仔细,结果考虑情况就变得复杂多了)

2)将S中除开B中的顶点移动到W中

这样或许能使S中总的顶点个数减少。

由于上面的第一个条件:可以将B中与S中任一顶点相连的顶点送到S中,而且要去在将S中的顶点移动到W中时,一定不能是B移动到S中,其实这个条件没有用,因为已经很清晰了。因为从B中送入S中的是与S中某一顶点严格左相连的,而且由分析可知S送入W是从右到左连带传送,而每一行又必须要存在一个元素,故B中送入S中的一定可以保留在S中,即在考虑传送时,就可以一起以相同方式考虑了:左边若传送了,在右边可以不传送,当然也可以传送;右边传送了,则左边必须全部传送。

那么就可以将题目转化为我们习惯的常见搜索题了:即n*m的矩阵,可以移动的点位S中本身的点+B中可以移动到S中的点,然后就是从每一行的点移动的方式与三种,分别为下、左、右。而终点即使最后一行,搜索的目标就是S中的最小顶点数目。

这里还要注意一点:题目要求不S中的点不能是矩形的四个顶点,而实际考虑时,只需要考虑右边上下的两个顶点就可以了。

下面是代码: TLE代码(没有考虑严格左相连情况下复杂处理的代码)仅供参考

Source CodeProblem: 2056  User: 1294057873 Memory: N/A  Time: N/A Language: C++  Result: Time Limit Exceeded Source Code #include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 210bool flag[Max][Max];int record[Max][Max];int line[Max][2];int n,m;int Sum;void dfs(int x,int y,int Count){if(x==2 && y==1 || x==2 && y==m|| x==n+1 && y==1 || x==n+1 && y==m    || x==1 && y==1 || x==1 && y==m|| x==n && y==1 || x==n && y==m)    return ;if(Count>=Sum)return ;if(x==n+1){Sum=Count;return ;}if(record[x][y]==1 && !flag[x][y])return ;if(record[x][y]==-1)return ;if(y<=line[x][1]+1){dfs(x+1,y,Count+1);int number=Count+1;/*for(int i=y-1;i>=line[x][0];i--)dfs(x+1,i,++number);number=Count+1;for(int i=y+1;i<=m;i++){if(record[x][i]==1 && !flag[x][i])break;dfs(x+1,i,++number);}*/int pivot1=y-1,pivot2=y+1;while(pivot1>=line[x][0] && pivot2<=m){dfs(x+1,pivot1,++number);pivot1--;dfs(x+1,pivot2,number);pivot2++;}while(pivot1>=line[x][0]){dfs(x+1,pivot1,++number);pivot1--;}while(pivot2<=m){dfs(x+1,pivot2,++number);pivot2++;}}else{int temp=Count+y-line[x][1];for(int i=line[x][1]+1;i>=line[x][0];i--)dfs(x+1,i,++temp);}}int main(){int i,j;while(scanf("%d%d",&n,&m),n){memset(flag,0,sizeof(flag));memset(record,-1,sizeof(record));Sum=0;for(i=1;i<=n;i++){getchar();bool trag=true;for(j=1;j<=m;j++){char temp=getchar();if(temp=='S'){Sum++;record[i][j]=0;if(trag){trag=false;line[i][0]=j;}}else if(temp=='B'){record[i][j]=1;if(!trag){trag=true;    line[i][1]=j-1;}}}}for(i=1;i<=n;i++)flag[i][line[i][1]+1]=true;for(i=line[1][0];i<=m;i++){if(record[1][i]==0){dfs(1,i,0);}else if(record[1][i]==1 && flag[1][i]){dfs(1,i,0);}elsebreak;}printf("%d\n",Sum);}return 0;}

下面是用深搜TLE代码(仅供参考):

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 210bool record[Max][Max];bool flag[Max][Max];int dir[3][2]={{1,0},{0,-1},{0,1}};int n,m;int Sum;void dfs(int x,int y,int Count){if(Count+1>=Sum)return ;if(x==n){Sum=Count+1;return ;}for(int i=0;i<3;i++){int tx=x+dir[i][0],ty=y+dir[i][1];if(record[tx][ty] && !flag[tx][ty]){flag[tx][ty]=true;dfs(tx,ty,Count+1);flag[tx][ty]=false;}}}int main(){int i,j;while(scanf("%d%d",&n,&m),n|m){memset(record,0,sizeof(record));    memset(flag,0,sizeof(flag));    Sum=0;for(i=1;i<=n;i++){getchar();bool trag=true;for(j=1;j<=m;j++){char temp=getchar();if(temp=='S'){record[i][j]=1;Sum++;}else if(temp=='B' && trag){trag=false;if((i==1 && j==m) || (i==n && j==m))
                                               continue;
record[i][j]=1;}}}for(i=1;i<=m;i++)if(record[1][i]){flag[1][i]=true;dfs(1,i,0);flag[1][i]=false;}printf("%d\n",Sum);}return 0;}

最后是BFS AC代码: 304K+47MS

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 210bool record[Max][Max];bool flag[Max][Max];int dir[3][2]={{1,0},{0,-1},{0,1}};int n,m;int Sum;struct Node{int x,y;int num;}node[Max*Max];void bfs(int x,int y){int pivot=0,index=0,tx,ty;memset(flag,0,sizeof(flag));node[pivot].x=x,node[pivot].y=y;node[pivot++].num=1;flag[x][y]=true;while(index<pivot){if(node[index].num>=Sum)return ;if(node[index].x==n){Sum=node[index].num;return ;}tx=node[index].x,ty=node[index].y;//printf("%d %d\n",tx,ty);for(int i=0;i<3;i++){int ttx=tx+dir[i][0],tty=ty+dir[i][1];if(record[ttx][tty] && !flag[ttx][tty]){flag[ttx][tty]=true;node[pivot].x=ttx,node[pivot].y=tty;node[pivot++].num=node[index].num+1;}}index++;}}int main(){int i,j;while(scanf("%d%d",&n,&m),n|m){memset(record,0,sizeof(record));    Sum=0;for(i=1;i<=n;i++){getchar();bool trag=true;for(j=1;j<=m;j++){char temp=getchar();if(temp=='S'){record[i][j]=1;Sum++;}else if(temp=='B' && trag){trag=false;if((i==1 && j==m) || (i==n && j==m))continue;elserecord[i][j]=1;}}}for(i=1;i<=m;i++)if(record[1][i])bfs(1,i);printf("%d\n",Sum);}return 0;}

 

0 0
原创粉丝点击