机器人捡硬币(动态规划)

解题思路

在这里插入图片描述

代码实现:

#include<iostream>
using namespace std;

#define n 5
#define m 6

int v[n + 1][m + 1];//有硬币格子分布情况,主函数中初始化
int list[n + 1][m + 1] = { 0 };//表格,初始化
int route[n + 1][m + 1] = { 0 };//经过的位置置一


int max(int a, int b) {//用于比较上左两个位置最优情况大小
	if (a > b)
		return a;
	else
		return b;
}




int KnapSack(int v[n+1][m+1],int list[n+1][m+1]) {//从左至右,从上至下,填表
	int i, j;
	for (i = 1; i <= n; i++) {//从(1,1)开始填表
		for (j = 1; j <= m; j++)
		{
			list[i][j] = v[i][j] + max(list[i - 1][j],list[i][j - 1]);
		}
	}
	return list[n][m];
}


void judge(int list[n + 1][m + 1], int v[n + 1][m + 1],int num) {
	int i, j,flag=0;
	i = n;
	j = m;
	route[n][m] = 1;
	while (i != 1 || j != 1) {//i,j同时为1停止循环
		if ((list[i][j] - v[i][j]) == list[i - 1][j] && (list[i][j] - v[i][j]) != list[i][j - 1])
		{
			route[i - 1][j] = 1;
			i = i - 1;
		}

		else if((list[i][j] - v[i][j]) == list[i][j-1] && (list[i][j] - v[i][j]) != list[i-1][j]){
			route[i][j-1] = 1;
			j = j - 1;
		}
		else {
			route[i][j - 1] = 1;
			route[i - 1][j] = 1;
			i = i - 1;
			j = j - 1;
		}
	}
	
}


int main() {
	v[2][2] = 1;v[1][5] = 1;v[2][4] = 1;v[3][4] = 1;v[3][6] = 1;
	v[4][3] = 1;v[4][6] = 1;v[5][1] = 1;v[5][5] = 1;
	int num;

	num=KnapSack(v, list);
	judge(list,  v,  num);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cout << route[i][j] << " ";
			if (j == 6)cout << endl;
		}
	}
	return 0;
}

运行结果:
在这里插入图片描述

在以上代码的基础上,用graphics实现可视化


#include <graphics.h>      // 引用图形库头文件
#include<stdlib.h>
#include<string.h>
#include <conio.h>
#include<iostream>

#pragma comment(lib,"MSIMG32.LIB")

using namespace std;

#define wSpace 193//棋盘的以左部分像素宽度
#define hSpace 114//棋盘以上的像素宽度
#define wz 55//半个格子的宽度
#define hz 46//半个格子的高度
#define r 32//圆的半径
#define n 5//棋盘规格n*m
#define m 6
#define rw 90//机器人的宽和高
#define  rh 71

int num;
int v[n + 1][m + 1];//有硬币格子分布情况,主函数中初始化
int list[n + 1][m + 1] = {
    
     0 };//表格,初始化
int route[n + 1][m + 1] = {
    
     0 };//经过的位置置一


IMAGE welcome;//初始界面
IMAGE welcome_button;//点击效果
IMAGE ending;//结束界面
IMAGE chessboard;//棋盘
IMAGE robot;//机器人
IMAGE robotx;


void Ending()
{
    
    
	Sleep(1000);
	MessageBox(NULL, _T("程序运行完毕!"), _T("提示"), MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION);
	loadimage(&ending, L"end.jpg");//导入结尾
	putimage(0, 0, &ending);
}

//棋盘中硬币的位置
void draw_point()
{
    
    
	
	//2,2  1,5  2,4  3,4  4,3  5,1  3,6   4,6  5,5
	setfillcolor(RED);
	//fillcircle(wSpace + wz, hSpace + hz, r);//起始点
	fillcircle(wSpace + 11*wz, hSpace + 9*hz, r);//终点
	setfillcolor(LIGHTBLUE);
	fillcircle(wSpace + 3 * wz, hSpace + 3 * hz, r);//(坐标*2-1)*半个格子的高||宽+初始值==硬币实际位置
	fillcircle(wSpace + 9 * wz, hSpace + 1 * hz, r);
	fillcircle(wSpace + 7 * wz, hSpace + 3 * hz, r);
	fillcircle(wSpace + 7 * wz, hSpace + 5 * hz, r);
	fillcircle(wSpace + 5 * wz, hSpace + 7 * hz, r);
	fillcircle(wSpace + 1 * wz, hSpace + 9 * hz, r);
	fillcircle(wSpace + 11 * wz, hSpace + 5 * hz, r);
	fillcircle(wSpace + 11 * wz, hSpace + 7 * hz, r);
	fillcircle(wSpace + 9 * wz, hSpace + 9 * hz, r);
	//getchar();
	Sleep(1000);
}




void transparentimage(IMAGE *dstimg, int x, int y, IMAGE *srcimg)//半透明输出图片,隐藏背景。
{
    
    
	HDC dstDC = GetImageHDC(dstimg);
	HDC srcDC = GetImageHDC(srcimg);
	int w = srcimg->getwidth();
	int h = srcimg->getheight();
	BLENDFUNCTION bf = {
    
     AC_SRC_OVER,0,255,AC_SRC_ALPHA };
	AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
}


void twindows() {
    
    
	int x1, y1;//robot在起点时,左上角的位置
	int x2 = 0, y2 = 0;
	int x3, y3;
	x1 = 20 + wSpace;
	y1 = 20 + hSpace;
	x3 = x1;
	y3 = y1;
	MessageBox(NULL, _T("棋盘大小为5*6"), _T("提示"), MB_OK|MB_SETFOREGROUND|MB_ICONWARNING);
	Sleep(1000);
	loadimage(&chessboard, L"chessboard.jpg");//导入棋盘
	loadimage(&robot, L"robot.jpg");//导入机器人
	putimage(0, 0, &chessboard);//显示
	transparentimage(NULL,x1 , y1 , &robot);//显示
	draw_point();
	getimage(&robotx, x1, y1, rw, rh);
	setlinecolor(RED);
	
	for (int i = 1; i <= n; i++)
	{
    
    
		for (int j = 1; j <= m; j++)
		{
    
    
			if (route[i][j] == 1) {
    
    
				x2 = (j - 1)*2*wz+x1;//下一个位置上,图形的左上角点的坐标
			    y2 = (i - 1)*2*hz+y1-5;//
				line(x3, y3, x2, y2);
				Sleep(100);
				putimage(x2, y2, &robotx);
				x3 = x2;
				y3 = y2;
			}
		}
	}
	RECT A1 = {
    
     900,650,1049, 700 };

	wchar_t temp[30];
	_stprintf_s(temp, _T("硬币数量为:%d"), num);
	drawtext(temp, &A1, DT_WORDBREAK);
	Ending();
	Sleep(1000);
	closegraph();
}

//欢迎界面函数
void Welcome()
{
    
    
	initgraph(1049, 700, EW_SHOWCONSOLE | EW_NOCLOSE);//定义窗口大小
	loadimage(&welcome, L"welcome.jpg");//导入欢迎界面(特别注意:双引号里面不能有空格,要跟图片命名完全一致)
	putimage(0, 0, &welcome);//显示欢迎界面
	/*下面进行鼠标交互*/
	MOUSEMSG msg;//定义变量,保存鼠标消息
	FlushMouseMsgBuffer();// 清空鼠标消息缓冲区,避免无效鼠标信息带入到正式判断中
	while (true) // 主循环,循环监听鼠标信息
	{
    
    
		while (MouseHit())	//监听鼠标信息;当有鼠标消息的时候执行,可检测连续的鼠标信息
		{
    
    
			msg = GetMouseMsg();//获取鼠标消息
			if (WM_LBUTTONDOWN == msg.uMsg)//判断鼠标信息;鼠标左键按下
			{
    
    
				if (msg.x > 417&& msg.x < 667 && msg.y > 516 && msg.y < 596)//鼠标点击特定区域,即ENTER按钮所在区域
				{
    
    
					loadimage(&welcome_button, L"welcome_button.jpg");//导入橙色按钮图片
					putimage(0, 0, &welcome_button);//显示橙色按钮图片
					Sleep(100);//延时,降低CPU占用率,并且做到点击效果
					twindows();
				}
			}
		}
	}
}



int bigger(int a, int b) {
    
    //用于比较上左两个位置最优情况大小
	if (a > b)
		return a;
	else
		return b;
}




int KnapSack(int v[n + 1][m + 1], int list[n + 1][m + 1]) {
    
    //从左至右,从上至下,填表
	int i, j;
	for (i = 1; i <= n; i++) {
    
    //从(1,1)开始填表
		for (j = 1; j <= m; j++)
		{
    
    
			list[i][j] = v[i][j] + max(list[i - 1][j], list[i][j - 1]);
		}
	}
	return list[n][m];
}

/*用route数组记录经过的路线,置一*/
void judge(int list[n + 1][m + 1], int v[n + 1][m + 1]) {
    
    
	int i, j, flag = 0;
	i = n;
	j = m;
	route[n][m] = 1;
	while (i != 1 || j != 1) {
    
    //i,j同时为1停止循环
		if ((list[i][j] - v[i][j]) == list[i - 1][j] && (list[i][j] - v[i][j]) != list[i][j - 1])
		{
    
    
			route[i - 1][j] = 1;
			i = i - 1;
		}

		else if ((list[i][j] - v[i][j]) == list[i][j - 1] && (list[i][j] - v[i][j]) != list[i - 1][j]) {
    
    
			route[i][j - 1] = 1;
			j = j - 1;
		}
		else {
    
    
			route[i][j - 1] = 1;
			route[i - 1][j] = 1;
			i = i - 1;
			j = j - 1;
		}
	}

}


int main() {
    
    
	v[2][2] = 1; v[1][5] = 1; v[2][4] = 1; v[3][4] = 1; v[3][6] = 1;
	v[4][3] = 1; v[4][6] = 1; v[5][1] = 1; v[5][5] = 1;
	num = KnapSack(v, list);
	judge(list, v);
	cout << "机器人的脚印如下图所示:" << endl;
	for (int i = 1; i <= n; i++)
	{
    
    
		for (int j = 1; j <= m; j++)
		{
    
    
			cout << route[i][j] << " ";
			if (j == 6)cout << endl;
		}
	}

	Welcome();
	return 0;
}

运行结果:
在这里插入图片描述

编程中遇到的问题

1.使用ps对图片像素定位不精确,存在误差。
2.transparentimage函数并没有隐藏背景。
3.机器人在有多种选择时,代码描述不够完善。

可视化参考材料:链接: link.

猜你喜欢

转载自blog.csdn.net/qq_43318654/article/details/106008925