POJ1979

算法各种不给力,但是慢慢的研究下来发现其实挺有意思的。自己当时觉得老师讲得太水了,就毅然决然的没有选择算法课,但是大学四年我也咩有好好学习过算法。

突然想到大学就这么被我荒废掉的这么多旧时光,真是让人感伤。大哭


想想上次去清华面试的时候,师兄问我们考试的情况,大家都说题目最后一题比较难,然后他听大家讲完题目之后,秒杀了最后一题,然后我就默默的跪倒了。

果真和清华的小朋友们有质的差距。。。难过第二天早上一电信的哥们十分自信的在描述最后一题是如何简单的时候,然后我就默默的慌张了,因为我压根就

不会,除了第一题飞快的搞定了之后。然后就自信满满的没有检查,导致一个月后回想起来都还纳闷第一题是循环输入还是单词输入的问题上心惊肉跳了一个月。

以前总是喜欢规避问题,然后当不得不面临问题的时候其实我什么也做不好。我学计算机网络的时候也是这个样子的,之前一个老师讲得非常好,然后换了个老师

立马开始水了。今天和小学弟在讨论网络的问题的时候,他问我没学过计算机网络么,然后我默默的忧伤了,曾几何时我是下了决心要以后死磕网络,然后读网络的

DR,现在看来好像本科不过关呢。委屈

呀呀,明天又要继续奋斗了。


虽然今天搞了一天大家都认为很水的一道搜索算法题,但是我认认真真的想了才想出来的,虽然在VS通过了测试用例,但是悲剧的是过OJ的时候报了一个WA,郁闷。

仔细对比了一下网上的代码,是一样一样的,不管了。先回顾一下煎熬史。

哦,对了,之前学的C++大概是在某几次便便之后都拿去浇花了,所以导致我现在记不起一点C++,所以我明天开始要开始复习C++。

不对,明天要写开题报告。


今天死磕了一天,先总结一下问题,方便以后查缺补漏,提高自我,哈哈~

  • C++各种不给力,很多方便的方法都不会用
  • C语言的基础知识忘记了很多,比如说scanf()?就有遗忘
  • 一些很好的编程技巧没有掌握,比如说scanf("%d\n",&x);这种语句是可以的,其次就是scanf的返回值问题
  • 其次C语言的string.h用的还是各种不熟悉啊
  • 代码还是很挫,需要进步
  • 算法还是看少了,看少了!!!!
总之,每天一AC,快乐生活每一天,呀呀,狗狗加油!奋斗

进入正题:
Red and Black
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 20850 Accepted: 11150

Description

There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles. 

Write a program to count the number of black tiles which he can reach by repeating the moves described above. 

Input

The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20. 

There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows. 

'.' - a black tile 
'#' - a red tile 
'@' - a man on a black tile(appears exactly once in a data set) 
The end of the input is indicated by a line consisting of two zeros. 

Output

For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).


有一个矩形的房间,里面铺满了方形的瓷砖。每一个瓷砖有红色还有黑色两种,人只能站在黑色的瓷砖上不能站在红色的瓷砖上,每次只能走前后左右四个方向的四个瓷砖,计算能够到达的黑色瓷砖的总面积数。


首先这题的输入有个小track,有个小陷阱,那就是每一行数组里的末尾都会有一个\n换行符,刚开始的时候并没有注意到这个问题发现输出的结果比较诡异,然后调试的时候发现了这个问题。
之后设置了一个字符char c 用getchar()方法把这个字符吸收了,不够后来发现还有更好的解决办法。

昨天想了一下这个题觉得并不难,之后实现却花了一天,最后跑OJ的时候还是WA真是伤感情~
输入时表示列以及行:
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.

想到的思路就是从该点向上下左右四个方向进行遍历,将可以走的地方设置为#直到所有的地方都不可走为未知。看的代码不多,所以写出来有点扭曲。
算法采用的是DFS深度优先遍历算法。


如上图所示,人站在蓝色的位置,依次查找上下左右四个方向是不是可以走,我查找顺序是下左上右,当下面不行的时候测试一下左边边行不行,发现还不行,这个时候查找上面行不行,可以则上移。


这个时候在查找下面,是以前的位置,不行,左边可以

这个时候可以发现其实在当前所占的位置我们都需要判断该点上下左右可以走的方向,满足查找的条件那我们就可以走。
这个条件用话描述出来的话就是:if当前点在搜索的矩形范围内,并且根据查找顺序我们可以得到可以走的下一个点,那我们就走到那个瓷砖上。
用伪代码来表示就是:
//可走的下一个点
if(x >= 0 && x <= H && y >=0 && y < W && cango[x][y] == '.' )

这样对于来的每一个点的上下左右做一次判断就ok了
   DFS(p - 1, q);
   DFS(p, q - 1);
   DFS(p, q + 1);
   DFS(p + 1, q);

但是在此之前由于比较挫的算法功力,以及看的比较少的代码,导致写出了下面比较扭曲的代码片段:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_N 20
int W, H;
char a[MAX_N][MAX_N];
int res=1;
bool flag = false;
int dfs(int nx, int ny)
{
	
	//搜索下面
	if(nx>=0 && nx+1<H && ny>=0 && ny<W && a[nx+1][ny] =='.')
	{	
		nx = nx+1;
		a[nx][ny] = '#';
		res++;
		flag = true;
		dfs(nx,ny);
	} 

        //搜索左面
	 if(nx>=0 && nx<H && ny-1>=0 && ny<W && a[nx][ny-1]=='.')
	{	
		ny = ny-1;
		a[nx][ny] = '#';
		res++;
		flag = true;
		dfs(nx,ny);
	}

	//搜索上面 
	if(nx-1>=0 && nx<H && ny>=0 && ny<W && a[nx-1][ny] =='.')
	{
		nx = nx-1;
		a[nx][ny] = '#';
		res++;
		flag = true;
		dfs(nx,ny);
	}

        //搜索右面
	if(nx>=0 && nx<H && ny>=0 && ny+1<W && a[nx][ny+1]=='.')
	{	
		ny = ny +1;
		a[nx][ny] = '#';
		res++;
		flag = true;
		dfs(nx,ny);
	}
	
 	if(flag == false) 
		return res;

	return res;
}

int main()
{
	int nx=0,ny=0;
	char c;
	int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
	int x,y;

	while(scanf("%d%d\n",&W, &H) && (W || H)){for(int i=0; i<H; i++)
	{
		for(int j=0; j<W; j++)
		{
		 	scanf("%c",&a[i][j]);
			if(a[i][j]=='@')
			{ 
				nx = i;
				ny = j;
				a[nx][ny] = '#';
			}
		}
		c=getchar();
	}

	for(int i = 0; i < 4; i++)
	{
		x = nx + dx[i];
		y = ny + dy[i];
		if(a[x][y]=='.')
		{
			res=dfs(nx,ny);
		}
	}

	printf("%d\n",res);res=1;}
	//system("PAUSE");
	return 0;
}





最悲剧的事情就是无论如何也跑不出AC,到底是哪个情况没有考虑到啊????无论如何,在我睡了一天之后觉得代码可以改进,不自觉的看了看大神们的代码
果真需要恶补一下啊,总之比昨天比较挫的自己进步了一点点,还算比较欣慰吧,whatever,今天还是要继续
下面来看这哥们的代码:
//#define LOCAL
#include <stdio.h>
#include <string.h>

#define MAXN 20 + 10

char graph[MAXN][MAXN];
int m, n;
int result;

void DFS(int p, int q);

int main()
{
#ifdef LOCAL
	freopen("C:\\Users\\Administrator\\Desktop\\Temp\\ACMTempIn.txt", "r", stdin);
	//freopen("C:\\Users\\Administrator\\Desktop\\Temp\\ACMTempOut.txt", "w", stdout);
#endif


    int i, j;
    int p, q;
    while(scanf("%d%d", &n, &m) && m != 0)
    {
        // 数据的初始化
        result = 0;
        memset(graph, 0, sizeof(graph));

        // 数据输入
        for(i = 0; i < m; i++)
            for(j = 0; j < n; j++)
            {
                scanf("\n%c", &graph[i][j]);
                if(graph[i][j] == '@')
                {
                   p = i;
                   q = j;
                   graph[i][j] = '.';
                }
            }
         // 算法主体
         DFS(p , q);
         
         // 数据输出
         printf("%d\n", result);
    }

    return 0;
}

void DFS(int p, int q)
{
   if(p <= m - 1 && p >= 0 && q >= 0 && q <= n - 1 && graph[p][q] == '.')
   {
        result++;
        graph[p][q] = '#';
   }else {
        return;
   }
   
   DFS(p - 1, q);
   DFS(p, q - 1);
   DFS(p, q + 1);
   DFS(p + 1, q);
}

瞬间高大上了,呀呀,keep fighting~

今天在某人烦来烦去的情况下知道自己错在哪里了,当时思考的是到一个可行点之后就顺着一个方向一致往前走,除了在边界的时候才考虑其他情况
但是没走一步就应该向四周走,不能往一个方向走。 

经过改进之后的代码并且AC的代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_N 20
int W, H;
char a[MAX_N][MAX_N];
int res=0;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int x,y;
void dfs(int nx, int ny)
{
     if(nx >= 0 && nx < H && ny >= 0 && ny < W && a[nx][ny] =='.')
	 {
	     a[nx][ny] = '#';
		 res++;
	 }
	 else
		 return;

	 	for(int i = 0; i < 4; i++)
		{
			x = nx + dx[i];
			y = ny + dy[i];
			if(a[x][y]=='.')
			{
				dfs(x,y);
			}
		}	
	 
}	

int main()
{
	int nx=0,ny=0;
	
	while(scanf("%d%d\n",&W, &H) && (W || H))
	{
		for(int i=0; i<H; i++)
		{
			for(int j=0; j<W; j++)
			{
				scanf("%c",&a[i][j]);
				if(a[i][j]=='@')
				{
					nx = i;
					ny = j;
				}
			}
			getchar();
		}
		a[nx][ny] = '.';
		dfs(nx,ny);
	    printf("%d\n",res);
		res=0;
	}
	//system("PAUSE");
	return 0;
}






评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值