解题思路
代码实现:
#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.