Buggy Robot(Dijkstra + DP)

原题链接

参考

题意

在这里插入图片描述

思路

dp思路 + dijkstra

dp:

d [ i ] [ j ] [ k ] d[i][j][k] d[i][j][k] 表示用前k步时走到 ( i , j ) (i,j) (ij) ,最小的修改次数,

下面公式给的都只是一个大概意思,可以这样理解,实际上用优先队列版的Dijkstra时需要写成if判断的形式,判断最小值是否更新再放进队列。

添一步走: d [ x   +   x x [ i ] ] [ y   +   y y [ i ] ] [ k ]   =   m i n   (   d [ x ] [ y ] [ k ]   +   1 ,   d [ x   +   x x [ i ] ] [ y   +   x x [ i ] ] [ k ] ) d[x\ +\ xx[i]][y\ +\ yy[i]][k]\ =\ min\ (\ d[x][y][k]\ +\ 1,\ d[x\ +\ xx[i]][y\ +\ xx[i]][k]) d[x + xx[i]][y + yy[i]][k] = min ( d[x][y][k] + 1, d[x + xx[i]][y + xx[i]][k])

添一步走的思想就是我在当前这一步的基础上加一步,使它不走到操作序列中的下一个,使它的方案还在这一步中,但是位置变了操作次数也变了。

删一步走 d [ x ] [ y ] [ k + 1 ]   =   m i n   (   d [ x ] [ y ] [ k + 1 ] ,   d [ x ] [ y ] [ k ]   +   1 ) d[x][y][k + 1]\ =\ min\ (\ d[x][y][k + 1],\ d[x][y][k]\ +\ 1) d[x][y][k+1] = min ( d[x][y][k+1], d[x][y][k] + 1)

此处要注意K的大小,要控制在给的操作串长度以内,否则没意义还会死循环!

删一步走的意思是,在走下一步时不走下一步,所以还留在原位,但是实际上已经到下一步了,只是没有走而已,然后操作次数要+1;

直接走

此处要注意K的大小,要控制在给的操作串长度以内,否则没意义还会死循环!

如果走得了 d [ x + x x [ i ] ] [ y + y y [ i ] ] [ k + 1 ] = m i n ( d [ x + x x [ i ] ] [ y + y y [ i ] ] [ k + 1 ] , d [ x ] [ y ] [ k ] ) d[x + xx[i]][y + yy[i]][k + 1] = min(d[x + xx[i]][y + yy[i]][k + 1], d[x][y][k]) d[x+xx[i]][y+yy[i]][k+1]=min(d[x+xx[i]][y+yy[i]][k+1],d[x][y][k])

是直接走好还是到达那一步已经有了更好的走法

如果走不了(出界或撞墙) f [ x ] [ y ] [ k + 1 ] = m i n ( f [ x ] [ y ] [ k + 1 ] , f [ x ] [ y ] [ k ] ) f[x][y][k + 1] = min (f[x][y][k + 1], f[x][y][k]) f[x][y][k+1]=min(f[x][y][k+1],f[x][y][k])

下一步走不了所以还是留在原位,那么下一步到当前位置的操作步数可以用当前这一步来更新,因为反正动不了,也没有走,也不需要增加操作步数,看看是否要更新

Dijkstra

每次选操作次数最小的点,即距离最近的点作为队头,用它来更新所有连边,更新方式见上,然后把被更新了最短距离的点再放进队列,直到把所有距离都走完为止。

代码

#include<bits/stdc++.h> 
using namespace std;
const int N = 150;

int xx[4] = {1, 0, -1, 0};
int yy[4] = {0, 1, 0, -1};

struct node{
	int x; 
	int y;
	int k;//当前已经走过序列中的第几步,每次更新的都是它的后一步 
	int step;//第几次操作 
	 bool operator < (const node &b) const {
        return step > b.step;
    }
};

int n, m;
char g[N][N];
int d[N][N][N];
char s[N];
int len;
int sx, sy, ex, ey; //起点终点 

void bfs()
{
	priority_queue<node> q;
	q.push({sx, sy, 0, 0}); //放入起点 
	memset(d, 0x3f3f3f3f, sizeof d); //初始化距离
	d[sx][sy][0] = 0;
	
	while (!q.empty())
	{
		node t = q.top();
		q.pop();
		int x = t.x, y = t.y, k = t.k, step = t.step;
		if (g[x][y] == 'E') continue;
		
//		cout << x << " " << y << " " << k << " " << step << endl;
		
		//添一步走
		for (int i = 0; i < 4; i ++ ) 
		{
			int dx = x + xx[i];
			int dy = y + yy[i];
			
			//此处也要判断可以走,因为走不了没有意义 
			if (d[dx][dy][k] > step + 1 && dx >= 1 && dx <= n && dy >= 1 && dy <= m && g[dx][dy] != '#')
			{
				d[dx][dy][k] = step + 1; //更新距离
				q.push({dx, dy, k, step + 1}); //放入队列 
			}
		}
		
		if (k + 1 <= len) //防止死循环 
		{
			
			//删一步走 
			if (d[x][y][k + 1] > d[x][y][k] + 1) 
			{
				d[x][y][k + 1] = step + 1;
				q.push({x, y, k + 1, step + 1});
			}
			
			int dx = x, dy = y; 
			//直接走
			if (s[k + 1] == 'U') 
			{
				dx --;
			}
			else if (s[k + 1] == 'D')
			{
				dx ++;
			}
			else if (s[k + 1] == 'L')
			{
				dy --;
			}
			else if (s[k + 1] == 'R')
			{
				dy ++;
			}
			
			//如果可以走 
			if (dx >= 1 && dx <= n && dy >= 1 && dy <= m && g[dx][dy] != '#')
			{
				if (d[dx][dy][k + 1] > step)
				{
					d[dx][dy][k + 1] = step;
					q.push({dx, dy, k + 1, step});
				}
			}
			else //撞墙or出界 
			{
				if (d[x][y][k + 1] > step) 
				{
					d[x][y][k + 1] = step;
					q.push({x, y, k + 1, step});
				}
			}
		}
	}
}


int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i ++ )
	{
		for (int j = 1; j <= m; j ++ )
		{
			cin >> g[i][j];
			if (g[i][j] == 'R')
			{
				sx = i;
				sy = j;
			}
			if (g[i][j] == 'E')
			{
				ex = i;
				ey = j;
			}
		}
	}
	
	scanf("%s", s + 1);
	len = strlen(s + 1);
	bfs();
	int ans = 0x3f3f3f3f;
	for (int i = 0; i <= len; i ++ )
	{
		ans = min(ans, d[ex][ey][i]);
	}
	cout << ans << endl;
	return 0;
}

总结

好!好!好!

珍贵手记在这里插入图片描述

学习方法记录!

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 Moon-Buggy 的代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <curses.h> #include <time.h> #define VERSION "1.0" #define MAX(x,y) ((x) > (y) ? (x) : (y)) #define MIN(x,y) ((x) < (y) ? (x) : (y)) #define WIDTH 64 #define HEIGHT 16 #define PLAYER_POS_X 4 #define PLAYER_POS_Y (HEIGHT-3) #define DISTANCE_PER_FRAME 8 #define OBSTACLE_PERIOD 8 #define JUMP_DURATION 12 #define JUMP_HEIGHT 3 #define GRAVITY 1 #define SPRITE_GAP 2 static char player_up[] = {'O',0,'-','^',0,'|',0,0,'|',0,'^',0,'-',0,'O',0}; static char player_down[] = {'O',0,'-','v',0,'|',0,0,'|',0,'v',0,'-',0,'O',0}; static char obstacle1[] = {'*',' ',' ',0,'*','*',0,'*',' ',0,'*','*',0,'*',' ',0,'*',0}; static char obstacle2[] = {'*',0,0,'*',' ',0,'*','*',0,'*','*',0,'*',' ',0,'*',0,0}; static char *obstacles[] = {obstacle1, obstacle2}; static int sprite_widths[] = {16, 17}; static int obstacle_probabilities[] = {60, 40}; static int obstacle_y[] = {HEIGHT-3, HEIGHT-4}; static char *title[] = { "", " Moon Buggy", "", "", "", " Press SPACE to start", " Press Q to quit", "", " Version " VERSION, "", "", "", "", "", "", NULL }; static char *gameover[] = { "", "", "", " GAME OVER", "", "", "", " Press SPACE to restart", " Press Q to quit", "", "", "", "", "", "", NULL }; static char *score_prefix[] = { "SCORE: ", NULL }; static char score[16]; static int obstacle_pos = WIDTH-1; static int obstacle_type = 0; static int obstacle_speed = 1; static int obstacle_visible = 0; static int player_pos_y = PLAYER_POS_Y; static int player_speed_y = 0; static int player_jump_remaining = 0; static int distance = 0; static int score_length; static int frame_count = 0; static int frame_rate = 20; static int frame_period = 1000/frame_rate; static int screen_width = WIDTH+1; static int screen_height = HEIGHT+4; static WINDOW *win; static void draw_sprite(int x, int y, char *sprite, int width) { int i, j; for (i = 0; i < width; i++) { if (sprite[i]) { mvwaddch(win, y, x+i, sprite[i]); } } } static void draw_title() { int i; int y = (screen_height - sizeof(title)/sizeof(title[0])) / 2; for (i = 0; title[i]; i++) { mvwaddstr(win, y+i, (screen_width-strlen(title[i]))/2, title[i]); } } static void draw_gameover() { int i; int y = (screen_height - sizeof(gameover)/sizeof(gameover[0])) / 2; for (i = 0; gameover[i]; i++) { mvwaddstr(win, y+i, (screen_width-strlen(gameover[i]))/2, gameover[i]); } } static void draw_score() { sprintf(score, "%d", distance); mvwaddstr(win, 0, screen_width-score_length-1, score_prefix[0]); wattron(win, A_REVERSE); mvwaddstr(win, 0, screen_width-score_length-1+strlen(score_prefix[0]), score); wattroff(win, A_REVERSE); } static void draw_player() { if (player_jump_remaining) { draw_sprite(PLAYER_POS_X, player_pos_y, player_up, sprite_widths[0]); } else { draw_sprite(PLAYER_POS_X, player_pos_y, player_down, sprite_widths[1]); } } static void draw_obstacle() { if (obstacle_visible) { draw_sprite(obstacle_pos, obstacle_y[obstacle_type], obstacles[obstacle_type], sprite_widths[obstacle_type]); } } static void draw() { werase(win); draw_score(); draw_player(); draw_obstacle(); wrefresh(win); } static void update_player() { if (player_jump_remaining) { player_pos_y -= player_speed_y; player_speed_y -= GRAVITY; if (player_pos_y >= PLAYER_POS_Y) { player_jump_remaining = 0; player_pos_y = PLAYER_POS_Y; player_speed_y = 0; } } } static void update_obstacle() { if (++frame_count % OBSTACLE_PERIOD == 0) { if (!obstacle_visible) { obstacle_visible = 1; obstacle_type = rand() % 2; obstacle_pos = WIDTH - sprite_widths[obstacle_type]; obstacle_speed = 1 + rand() % 3; } } if (obstacle_visible) { obstacle_pos -= obstacle_speed; if (obstacle_pos < -sprite_widths[obstacle_type]) { obstacle_visible = 0; } } } static void update_distance() { distance += DISTANCE_PER_FRAME; score_length = strlen(score_prefix[0]) + strlen(score); } static void handle_input() { int c = getch(); if (c == ' ') { if (player_pos_y == PLAYER_POS_Y) { player_jump_remaining = JUMP_DURATION; player_speed_y = JUMP_HEIGHT; } else if (!obstacle_visible) { distance = 0; } } else if (c == 'q') { endwin(); exit(0); } } static void init() { initscr(); cbreak(); noecho(); curs_set(0); nodelay(stdscr, TRUE); win = newwin(screen_height, screen_width, 0, 0); srand(time(NULL)); } static void cleanup() { delwin(win); endwin(); } static void game_loop() { for (;;) { update_player(); update_obstacle(); update_distance(); draw(); handle_input(); if (player_pos_y == PLAYER_POS_Y && obstacle_visible && obstacle_type == 0 && obstacle_pos == PLAYER_POS_X && obstacle_y[0] == PLAYER_POS_Y) { draw_gameover(); wrefresh(win); while (getch() != ' ') { /* wait for space */ } distance = 0; obstacle_visible = 0; player_pos_y = PLAYER_POS_Y; player_speed_y = 0; player_jump_remaining = 0; frame_count = 0; } napms(frame_period); } } int main(int argc, char *argv[]) { init(); draw_title(); wrefresh(win); while (getch() != ' ') { /* wait for space */ } game_loop(); cleanup(); return 0; } ``` 这个代码是一个使用 curses 库的 Moon-Buggy 游戏。游戏中,玩家需要控制一辆月球车,躲避障碍物并尽可能地前进,直到撞上障碍物或按下 Q 键退出游戏。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值