暴力算法:图

1.油田
思路:
在mian函数中选出没有被标记的@,从它开始dfs;dfs函数遍历此@周边的符号,作用是给它们编上编号,直到一个八连块结束,退出一次dfs ;
代码:

#include<cstdio>
#include<cstring>
using namespace std ;

const int maxn = 100 + 5 ;
int idx[maxn] , m , n ;
char pic[maxn] ;
void dfs( int r , int c , int id ) {
	if( r < 0 || r >= m || c < 0 || c >= n ) return ;
	if( idx[r][c] > 0 || pic[r][c] != '@' ) return ;
	idx[r][c] = id ;
	for( int dr = -1 ; dr <= 1 ; dr ++ ) {
		for( int dc = -1 ; dc <= 1 ; dc ++ ){
			if( dr != 0 || dc != 0 ) dfs( r + dr , c + dc , id ) ;
		}
	}
}

int main() {
	while( scanf("%d%d",&m,&n) == 2 && m && n ) {
		memset( idx , 0 , sizeof(idx) ) ;
		for( int i = 0 ; i < m ; i ++ ) scanf("%s",pic[i]) ;
		int cnt = 0 ;
		for( int i = 0 ; i < m ; i ++ ) {
			for( int j = 0 ; j < n ; j ++ ) {
				if( pic[i][j] == '@' && idx[i][j] == 0 ) dfs( i , j , ++cnt ) ;
			}
		}
		printf("%d\n",cnt) ;	
	}
	return 0 ;
}

2.Abbott的复仇
1).创建转换函数、行走函数(根据当前状态和转弯方式,得到下一个状态);
2).构造bfs函数:构造队列q,先放入第一步,再while( !q.empty() ),放入v = walk ( u , i ) ;
3).打印结果:利用vector来保存路径,倒序输出
代码:

char *dirs = "NESW" ;
char *turn = "FLR" ;
int dir_id( char c ) {
	return strchr( dirs , c ) - dirs ;
}
int turn_id( char c ) {
	return strchr( turns , c ) - turns ;
}

const int dr[] = { -1 , 0 , 1 , 0 } ;
const int dc[] = { 0 , 1 , 0 , -1 } ;
Node walk( const Node &u , int turn ) {
	int dir = u.dir ;
	if( turn == 1 ) dir = ( dir + 3 ) % 4 ;
	if( turn == 2 ) dir = ( dir + 1 ) % 4 ;
	return Node( u.r + dr[dir] , u.c + dc[dir] , dir ) ;
}

void bfs() {
	queue<Node> q ;
	memset( d , -1 , sizeof(d) ) ;
	Node u( r1 , c1 , dir ) ;
	d[u.r][u.c][u.dir] = 0 ;
	q.push(u) ;
	while( !q.empty() ) {
		Node u = q.front() ;
		q.pop() ;
		if( u.r == r2 && u.c == c2 ) {
			print_ans(u) ;
			return ;
		}
		for( int i = 0 ; i < 3 ; i ++ ) {
			Node v = walk( u , i ) ;
			if( has_edge[u.r][u.c][u.dir][i] && inside( v.r , v.c ) && d[v.r][v.c][v.dir] < 0 ) {
				d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + 1 ;
				p[v.r][v.c][v.dir] = u ;
				q.push(v) ;
			}
		}		
	}
	printf("No Solution Possible\n") ;
}

void print_ans( Node u ) {
	vector<Node> nodes ;
	for( ; ; ) {
		nodes.push_back(u) ;
		if( d[u.r][u.c][u.dir] == 0 ) break ;
		u = p[u.r][u.c][u.dir] ;
	}
	nodes.push_back( Node( r0 , c0 , dir ) ) ;
	for( int i = nodes.size() - 1 ; i >= 0 ; i -- ) 
	printf(" (%d,%d)",nodes[i].r,nodes[i].c) ;
}

3.八数码问题(隐式图的bfs遍历)
思路:这道题用一个数组st和和两个数字代替了队列q的功能,以st[front]为父节点,st[rear]为子节点;
如图:
在这里插入图片描述
注意:
1).memcmp判定目标状态:

if( memcmp( goal , s , sizeof(goal) == 0 ) )
return front ;

2).扩展新结点:

State &t = st[rear] ;
memcpy( &t , &s , sizeof(s) ) ;

代码:

typedef int State[9] ;
const int maxn = 1000000 ;
State st[maxn] , goal ;
int dist[maxn] ;

const int dx[] = { -1 , 1 , 0 , 0 } ;
const int dy[] = { 0 , 0 , -1 , 1 } ;
int bfs() {
	int front = 1 , rear = 2 ;
	dist[1] = 0 ;
	while( front < rear ) {
		State &s = st[front] ;
		if( memcmp( goal , s , sizeof(goal) == 0 ) ) return front ;
		int z ;
		for( z = 0 ; z < 9 ; z ++ ) {
			if( s[z] == 0 ) break ;
		}
		int x = z / 3 ;
		int y = z % 3 ;
		for( int i = 0 ; i < 4 ; i ++ ) {
			int newx = x + dx[i] ;
			int newy = y + dy[i] ;
			int newx = newx * 3 + newy ;
			if( newx >= 0 && newx < 3 && newy >= 0 && newy < 3 ) {
				State &t = st[rear] ;
				memcpy( &t , &s , sizeof(s) ) ;
				t[z] = s[newz] ;
				t[newz] = s[z] ;
				dist[rear] = dist[front] + 1 ;
				rear ++ ;
			}
		} 
		front ++ ; 
	}
	return 0 ;
}

int main() {
	for( int i = 0 ; i < 9 ; i ++ ) scanf("%d",&st[1][i]) ;
	for( int i = 0 ; i < 9 ; i ++ ) scanf("%d",&goal[i]) ;
	int ans = bfs() ;
	if( ans > 0 ) printf("%d\n",dist[ans]) ;
	else printf("-1\n") ;
	return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值