Robots(机器人)

很遗憾,刚刚开始做OJ,南开大学的网站就挂了,难道老天看不惯我搞这个,有木有。???

不过北大依然刚硬,遂在北大随便找了道题如下:

Robots(机器人) http://poj.org/problem?id=1098


说明:
机器人游戏是一个在31x31棋盘上玩的单人游戏,棋盘被分割为1x1的单元并按31行31列排列,每一个单元被索引为(r,c),r代表行号,c代表列号(从1开始),单元有四种状态:1.空,2.被你占领 3.被机器人占领,4.被碎片占领。游戏的目标是按照一定的路径行动,在机器人摧毁你之前把所有的机器人摧毁。


初始状态,你占领 单元(15,15),并且棋盘上有R个机器人,(1<=R<=50),他们分布在不同于(15,15)的单元,其他单元为空。你还被给予了一张T(0<=T<=20)个单元的列表,这些单元的含有传送门。你先移动,然后是机器人,然后再是你。在你移动的过程中,你可以移动到相邻的八个罗盘方向的任意为空的单元,或者移动到传送门列表上的任意一个单元,或者静止不动。另外,你也可以移动到相邻的含有碎片的单元,但必须顺着你移动的路线,把碎片推到下一个相邻的不含碎片的单元。如果碎片被推到一个含有机器人的单元,那机器人就被摧毁。如果你选择传送,那么目的地址必须是个空单元。你不能进行任何会把你自己或碎片移出棋局的移动。


机器人移动时,每个机器人移动离你最近的到相邻单元(可以不为空),单元与单元的距离通过|r1-r2| +|c1-c2|计算 ,当两个机器人移动到相同单元或者移动到含有碎片的单元,机器人被摧毁。当任一机器人移动到你的当前位置时,你输掉游戏。如果两个机器人同时移动到你所在的位置,虽然机器人被摧毁,但是你依然输掉游戏,游戏结束。当所有的机器人都被摧毁,并且没有机器人移动到你的位置,你赢得游戏。


为了尽可能长的进行游戏,你可以仅考虑进行不会马上输掉的移动,一种貌似有理的策略是:总是保持不动或者进行移动之后,棋盘上剩余的机器人最少或者移动的最小。在两种移动相同下无法决定的情况下,选择离当前所有机器人最远的移动,如果还是无法决定,选择行号最小的单元移动,再无法决定,选择列号最小的单元移动。

如果任何一个移动或者保持都会导致游戏结束,你可以选择传送到列表上的任意一个合法的地方。当进行传送位置搜索时,你每次都应该从列表头开始查找。如果没有任何一个地方可以传送,你只能保持不动,并且输掉游戏。

在这个问题中,你将执行这种游戏策略,并且看看它是否能有效工作。

输入:
输入包含一系列的实例,每一个实例的第一行包含两个空格分隔的数字R,T ,然后紧跟着R行,每一行含有两个数字标识出R个机器人的初始位置。你可以假设每一个机器人占领一个除(15,15)外的不同单元,接下来的T行给出了传送门的位置,每一号包含一个行号和列号,当遇到(0,0)时,输入结束。

输出:
1.在每一个用例中,按照示例输出的格式 打印出用例号(从1开始).
2.每次传送时,按以下格式打印一行:
Move m: teleport to (r, c) 
  m 等于至传送时你执行的移动的个数(包括本次), (r,c)是你传送的单元地址。
3.如果你赢得游戏,打印以下3行:

Won game after making m moves. 
Final position (r,c) 
Number of cells with debris: d 

如果你输掉游戏,打印以下4行:

Lost game after making m moves. 

Final position: (r,c) 
Number of cells with debris: d 
Number of robots remaining: n 


示例输入:
4 0
17 18
13 18
8 12
10 12
4 0
17 17
13 17
13 13
17 13
3 3
17 18
13 18
5 31
15 16
16 15
3 7
0 0


示例输出:
Case 1:
Won game after making 5 moves.
Final position: (14,16)
Number of cells with debris: 1
Case 2:
Lost game after making 2 moves.
Final position: (15,15)
Number of cells with debris: 1
Number of robots remaining: 0
Case 3:
Move 30: teleport to (16,15)
Move 58: teleport to (15,16)
Move 86: teleport to (3,7)
Lost game after making 114 moves. 
Final position: (1,29)
Number of cells with debris: 1

Number of robots remaining: 1


解题思路:每一次移动都枚举出各种移动方法,选择最优的进行移动。


可做了一天依然没有AC,只有先放在这里了:

#include<iostream>
#include<list>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<map>
#include<utility>

using namespace std;

struct postion
{
	friend ostream &operator<<(ostream & os, postion &pos);
	postion(){}
	postion(int _x,int _y):x(_x),y(_y ) {}
	int x;
	int y;
	bool operator==(const postion &pos) const;
	bool operator<(const postion &pos) const;
	postion &operator=(const postion &pos);
	
};

bool postion::operator==(const postion &pos) const
{
	if(this->x==pos.x && this->y==pos.y )
		return true;
	else
		return false;
}

bool postion::operator<(const postion &pos) const
{
	return ( x<pos.x || ( (x==pos.x)? (y<pos.y) :false)  );
}
	
postion &postion::operator=(const postion &pos)
{	
	this->x=pos.x;
	this->y=pos.y;
	return *this;
}

ostream &operator<<(ostream & os, postion &pos)
{
	os<<"("<<pos.x<<","<<pos.y<<")";
	return os;
}

#define POS_EMPTY	0
#define POS_ROBOT 	1
#define POS_DEBRIS	-1
#define POS_PLAYER	-2
#define BROAD_NUM	32


#define Is_Valid_Pos(i,j)  (((i)>0 && (i)< BROAD_NUM)  && ((j) >0 && (j) < BROAD_NUM) )
#define DISTANT(Px,Py)  ( abs( (Px).x-(Py).x ) + abs( (Px).y -(Py).y ) )

class Game
{

public:
	Game();
	Game(const Game &game);
		
 	struct Is_Debris; 
	struct Is_Danger;
	struct Is_Safe;
	list<postion> robots;
	list<postion> debris;
	list<postion> teleport;
	int broad[BROAD_NUM][BROAD_NUM];
	postion player;
	
	//一切初始化
	void Init();
		
	//生成pos邻近的9个点坐标
	list<postion>  Compass(const postion &pos) const;
	list<postion>  Location(const postion &pos)  ;
	
	//是否能移动到新位置
	bool MoveCan(const postion &pos) const;
	
	//查找离robot离 player 最近的点
	postion Closest( const postion &robot, const postion &player) const;
	
	
	int Destory(list<postion> &p_list) ;
	void Destant();
	
	void Move();
	void Input(istream &in,int R, int T);
	
	bool IsSafe(const postion &pos) const;
	
	
	bool operator<(const Game &) const; 
	Game &operator=(const Game & game);
	
	
private:
	//计算列表中的重复值数目
	int Repeat(list<postion> &p_list) ;
	int Debris(list<postion> &p_list) ;
	int worth;
	int distant;
	int move;
	
	
};



struct Game::Is_Debris
{	
public:
	Is_Debris(const Game *_game);
	bool operator()(const postion &pos ) const;
	static int count;
private:
	const Game *game;
};

int Game::Is_Debris::count=0;
Game::Is_Debris::Is_Debris(const Game *_game):game(_game){}

bool Game::Is_Debris::operator()(const postion &pos ) const
{
	if(game->broad[ pos.x ][ pos.y] == POS_DEBRIS )
	{
		count+=1;
		return true;
	}
	return false;
}

struct Game::Is_Danger
{
public:
	Is_Danger(const Game *_game);
	bool operator()(const postion &pos ) const;
private:
	const Game *game;
};


Game::Is_Danger::Is_Danger(const Game *_game):game(_game){}

bool Game::Is_Danger::operator()(const postion &pos ) const
{
	if(game->broad[pos.x][pos.y] ==POS_DEBRIS )
		return false;
		
	return !game->IsSafe(pos);
}

struct Game::Is_Safe
{
public:
	Is_Safe(const Game *_game);
	bool operator()(const postion &pos ) const;
private:
	const Game *game;
};

Game::Is_Safe::Is_Safe(const Game *_game):game(_game){}

bool Game::Is_Safe::operator()(const postion &pos ) const
{
	return game->IsSafe(pos) && game->broad[pos.x][pos.y]==POS_EMPTY;
}


void Game::Init()
{
	memset(broad,0,sizeof(int) *BROAD_NUM * BROAD_NUM  );
	robots.clear();
	debris.clear();
	teleport.clear();
	player.x=player.y=15;
	broad[15][15]=POS_PLAYER;
	worth=0;
	distant=0;
	move=0;
}


list<postion> Game::Compass(const postion &pos) const
{
	list<postion> p_list;
	for(int i=pos.x-1; i<=pos.x+1 ;i++ )
	{
		for(int j=pos.y-1 ; j <= pos.y+1 ; j++  )
		{
			if( ! Is_Valid_Pos(i,j)   )
				continue;
			
			p_list.push_back( postion(i,j) );
		}
	}
	return p_list;
}


list<postion> Game::Location(const postion &pos)   
{
	list<postion> p_list=Compass(pos);
	list<postion>::iterator iter=remove_if(p_list.begin(), p_list.end() ,
							Game::Is_Danger(this) );

	p_list.erase(iter,p_list.end() );
	bool status=false;

	for(list<postion>::iterator iter=p_list.begin();iter!=p_list.end();
						iter++)
	{
		if( broad[iter->x][iter->y] ==POS_DEBRIS )
		{
			int x,y;
			x= iter->x-(player.x-iter->x );
			y= iter->y-(player.y-iter->y);
			if( Is_Valid_Pos(x,y) )
			{
				status=true;
				break;
			}
		}
		else
		{
			status=true;	
			break;
		}
	}

	if (status==false)
	{
		list<postion>::iterator iter=
			find_if(teleport.begin(),teleport.end(),Game::Is_Safe(this) );
		if (iter!=teleport.end())
			p_list.push_back(*iter);
	}

	if (p_list.size()==0)
	{
		p_list.push_back(player);
	}
	
	return p_list;
}

/*
list<postion> Game::Location(const postion &pos)   
{
	list<postion> p_list=Compass(pos);
	list<postion>::iterator iter=remove_if(p_list.begin(), p_list.end() ,
							Game::Is_Danger(this) );

	p_list.erase(iter,p_list.end() );
	bool status=false;

	for(list<postion>::iterator iter=p_list.begin();iter!=p_list.end();
						iter++)
	{
		if( broad[iter->x][iter->y] ==POS_DEBRIS )
		{
			int x,y;
			x= iter->x-(player.x-iter->x );
			y= iter->y-(player.y-iter->y);
			if( Is_Valid_Pos(x,y) )
			{
				status=true;
				break;
			}
		}
		else
		{
			status=true;	
			break;
		}
	}

	if (status==false)
	{
		list<postion>::iterator iter=
			find_if(teleport.begin(),teleport.end(),Game::Is_Safe(this) );
		if (iter!=teleport.end())
			p_list.push_back(*iter);
	}

	if (p_list.size()==0)
	{
		p_list.push_back(player);
	}
	
	return p_list;
}




*/



postion Game::Closest( const postion &robot, const postion &player) const
{
	int closest=70;
	list<postion> p_list=Compass( robot );
	postion ret_pos;
	for(list<postion>::const_iterator iter=p_list.begin(); 
					iter!=p_list.end() ;iter++  )
	{
		int distance=DISTANT( *iter , player );
						
		if(  distance < closest   )
		{
			closest=distance;
			ret_pos=*iter;
		}
	}
	
	return ret_pos;
}


int Game::Debris(list<postion> &p_list) 
{
	Game::Is_Debris::count=0;
	list<postion>::iterator iter=
				remove_if( p_list.begin(), p_list.end(),  Game::Is_Debris( this )  );
	p_list.erase(iter,p_list.end() );
	return Game::Is_Debris::count;
	 
}

int Game::Repeat(list<postion> &p_list) 
{
	map<postion,int> hash;
	for(list<postion>::const_iterator  iter=p_list.begin();
					iter!=p_list.end();iter++)
	{
		map<postion,int>::iterator it=hash.find( *iter );
		if(  it != hash.end()  )
			hash[*iter]++;
		else
			hash[*iter]=1; 
	}

	p_list.unique();
	
	int sum=0;
	for( map<postion,int>::iterator iter=hash.begin();
			iter!=hash.end( );iter++  )
	{
		if( iter->second > 1 )
		{
			sum+=iter->second;
			broad[iter->first.x ][ iter->first.y ]=POS_DEBRIS;
			debris.push_back( iter->first );
			p_list.remove(iter->first);
		}
	}
	
	return sum;
}

int Game::Destory(list<postion> & p_list) 
{	
	int value=0;
	value+=Repeat(p_list);
	value+=Debris(p_list);
	

	for (list<postion>::iterator iter=robots.begin();
					iter!=robots.end();iter++)
		broad[iter->x][iter->y]=POS_EMPTY;

	for (list<postion>::iterator iter=p_list.begin();
		iter!=p_list.end();iter++)
		broad[iter->x][iter->y]=POS_ROBOT;


	return value;	
}


void Game::Destant()
{
	int tmp;
	distant=100;
	for(list<postion>::iterator iter=robots.begin();
						iter!=robots.end() ;iter++)
	{	
		tmp=DISTANT( *iter,player);
		if( tmp<distant )
			distant=tmp;
	}
	
}

/*
compass:生成可以移动到得位置列表:包括传送。
*/

void Game::Move()
{
	int time=0;
	bool win=true;
	while(  robots.size()!=0 )
	{
		if (broad[player.x][player.y]!=POS_PLAYER )
		{
			win=false;
			break;
		}
		
		time+=1;
#ifdef DEBUG
		cout<<"move "<< (time) <<endl;
		cout<<"player("<<player.x<<","<<player.y<<")"<<endl;
#endif 
		if (time==113)
		{
			time++;
			time--;
		}
		list<postion> location=Location(player);
	
		
		list<Game> g_list;
		for(list<postion>::const_iterator iter=location.begin();
					iter!=location.end(); ++iter )
		{	
			Game g(*this);
			int worth=0;

			if ( DISTANT( (*iter) , player ) >2 )
			{
				cout<<"Move "<<time<<": teleport to ("<< iter->x<<","<<iter->y<<")"<<endl;
			}
			else if( g.broad[iter->x][iter->y] ==POS_DEBRIS )
			{
				int x,y;
				x= iter->x-(g.player.x-iter->x );
				y= iter->y-(g.player.y-iter->y);
				if( !Is_Valid_Pos(x,y) )
					continue;
				
				g.debris.remove( *iter );
				g.debris.push_back( postion(x,y) );	
				
				if(g.broad[x][y]==POS_ROBOT)
				{	
					worth+=1;
					g.robots.remove( postion(x,y) ); //destory a robot.
				}
				g.broad[x][y]=POS_DEBRIS;
			}

			g.broad[player.x][player.y]=POS_EMPTY;
			g.broad[iter->x][iter->y]=POS_PLAYER;
			g.player=*iter;
			
			
			
			int r_move=0;
			list<postion> np_list;
			for(list<postion>::iterator r_iter=g.robots.begin();
								r_iter!=g.robots.end() ;r_iter++ )
			{
				postion  closet=g.Closest(*r_iter, g.player );
				np_list.push_back( closet );
				r_move+=DISTANT(*r_iter, closet  );
			}
			move=r_move;
			worth+=g.Destory(np_list);
			g.worth=worth;
			g.robots=np_list;
			g.Destant();
			g_list.push_back(g);
		}
		
#ifdef DEBUG
		for (list<Game>::iterator iter=g_list.begin();iter!=g_list.end();iter++)
		{
		/*	cout<<" player:"<<iter->player
				<<" distant:"<<iter->distant
				<<" worth:"<<iter->worth
				<<" robots:"<<iter->robots.size()
				<<" debris:"<<iter->debris.size()<<" ";*/

			for (list<postion>::iterator p_iter=iter->debris.begin();
								p_iter!=iter->debris.end();p_iter++ )
			{
				cout<<"debris:"<<*p_iter<<endl;
			}
			for (list<postion>::iterator p_iter=iter->robots.begin();
				p_iter!=iter->robots.end();p_iter++ )
			{
				cout<<"robots:"<<*p_iter<<endl;
			}
			cout<<endl;
		}
		
#endif
	list<Game>::iterator iter=max_element( g_list.begin(),g_list.end() );
		this->operator=(*iter);
		this->worth=0;
		this->distant=0;
		
	}
	if (broad[player.x][player.y]==POS_DEBRIS)
		win=false;

	

	if(win)
		cout<<"Won game after making "<<time<<" moves."<<endl;
	else
		cout<<"Lost game after making "<<time-1<<" moves."<<endl;
	
	cout<<"Final position: ("<<player.x<<","<<player.y<<") "<<endl;
	cout<<"Number of cells with debris: "<<debris.size()<<endl;
	
	if(!win)
		cout<<"Number of robots remaining: "<<robots.size()<<endl;
	cout<<endl;
	
}

bool Game::operator<(const Game &game) const
{
	if(worth<game.worth )
		return true;
	else if (worth > game.worth)
		return false;

	if(distant<game.distant )
		return true;
	else if (distant > game.distant)
		return false;
		
	if(player.x > game.player.x)
		return true;
	else if(player.x < game.player.x)
		return false;
		
	if(player.y > game.player.y)
		return true;
	else if(player.y < game.player.y)
		return false;
	
	assert(0);
	return false;
	
}

Game & Game::operator=(const Game & game)
{
	memcpy(broad,game.broad, sizeof(int) *BROAD_NUM *BROAD_NUM );
	robots=game.robots;
	debris=game.debris;
	teleport=game.teleport;
	player=game.player;
	worth=game.worth;
	distant=game.distant;
	
	return *this;
}

bool Game::IsSafe(const postion &pos) const
{
	list<postion> p_list=Compass(pos);
	for(list<postion>::iterator iter=p_list.begin();
					iter!=p_list.end(); 
					iter++)
	{
		if( broad[iter->x][iter->y]==POS_ROBOT )
			return false;
	}
	return true;
}


Game::Game(const Game &game)
{
	this->operator=(game);
}

Game::Game(){}

void Game::Input(istream &cin,int R,int T)
{
	int r,c;
	for(int i=0;i<R;i++)
	{
		cin>>r>>c;
		assert( (r>0 && r< BROAD_NUM)  && (c >0 &&c <BROAD_NUM)  );
		robots.push_back( postion(r,c) );
		broad[r][c]=POS_ROBOT;
	}
	
	for(int i=0;i<T;i++)
	{	
		cin>>r>>c;
		assert( (r>0 && r<BROAD_NUM)  && (c >0 &&c < BROAD_NUM)  );
		teleport.push_back( postion(r,c) );
	}
}

#include <fstream>
  
int main()
{
	int R,T;
	Game game;
	int Case=1;
	ifstream in("input");
	while(cin>>R>>T)
	{
		if(R==T&&R==0)
			break;
		cout<<"Case "<<Case<<endl;
		game.Init();
		game.Input(cin,R,T);
		game.Move();
		Case++;
	}
}










  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值