c语言-收集样本问题

问题描述:

机器人Rob在一个有n*n个方格的方形区域F中收集样本。(i,j)方格中样本的价值为v(i,j),如图所示。Rob从方形区域F的左上角A点出发,向下或向右行走,直到右下角的B点,在走过的路上,收集方格中的样本。Rob从A点到B点共走两次,试找出Rob的2条行走路径,使其取得的样本总价值最大。

图示 n*n个方格的方形区域F
算法设计:
给定方形区域F中的样本分布,计算Rob的2条行走路径,使其取得的样本总价值最大。
数据输入
由文件input.txt给出输入数据。第一行有1个正整数n,表示方形区域F有n*n个方格。接下来每行有3个整数,前2个数表示方格位置,第3个数为该位置样本价值。最后一行是3个0。
结果输出
将计算的最大样本总价值输出到文件output.txt。

输入文件示例
input.txt output.txt
8 67
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0

设计思路:
要求出机器人两次收集样本的总价值,我们可以每次都找出样本地图中价值最大的路径,一共走两次。
另外定义一个价值地图,地图中每个网格的值代表走到当前网格经过的样本总价值。因为只能向右向下走,因此我们只需要取该网格左边和上面值较大的一个加上当前网格原本的样本值即为更新后的网格。
第一次过后找出的是样本价值最大的一条路径,然后我们可以把第一次经过的所有样本点的值更新为0,然后第二次重复此过程,即可找出两次行走路径取得样本总价值最大的路径。
valueMap中终点的值即为本次样本行走路径经过的样本最大总价值。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define MAXM 20
#define MAX(a, b) ((a) > (b) ? (a) : (b))

//存放经过点的横纵坐标
struct visited {
	int x , y;
};

//收集一次经过地图的样本
int collectSample ( int sampleMap[MAXM][MAXM] , int n )
{
	//生成样本地图的价值地图,为了方便统一处理,我将valueMap第0行第0列全部设置为0,
	//即相当于将原地图向右下角移动了一个位置(哨兵思想)
	int valueMap[MAXM][MAXM] = { 0 };
	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= n; ++j)
		{
			valueMap[i][j] = sampleMap[i - 1][j - 1];
			valueMap[i][j] += MAX ( valueMap[i - 1][j] , valueMap[i][j - 1] );
		}
	}
	printf ( "\n本次行走路径样本总价值最大为:%d" , valueMap[n][n] );
	
	//由于只能向左向下走,所以总的路径长度为2*n-2(不包含起点)
	const int pathLen = n * 2 - 2;
	visited path[MAXM * 2];
	for (int i = n , j = n , k = 0; k < pathLen; ++k)
	{
		path[k] = { i - 1, j - 1 };
		int prevValue = valueMap[i][j] - sampleMap[i - 1][j - 1];
		//i>1判断是否可以向左走,如果不可以就一定是向上走
		i>1&&valueMap[i - 1][j] == prevValue ? --i : --j ;
	}
	printf ( "\n经过的路径为:" );
	for (int k = pathLen-1; k >=0; --k)
	{
		printf ( "\n(%d,%d) %d" , path[k].x , path[k].y , sampleMap[path[k].x][path[k].y] );
		//对于走过的样本值置为0,方便第二次计算样本价值
		sampleMap[path[k].x][path[k].y] = 0;
	}
	return valueMap[n][n];
}

//读取文件填充样本地图
bool fillSampleMap ( int SampleMap[MAXM][MAXM] , int& n )
{
	FILE* f = fopen ( "D:\\学习\\大三上\\算法设计与分析\\实验四报告+附件\\input(1).TXT" , "r" );
	if (f == NULL)
	{
		printf ( "打开文件错误" );
		return false;
	}

	fscanf ( f , "%d" , &n );
	//题目说了i,j,x不同时为0即可,因此for循环中前面的==3的判断也可以不要
	for (int i , j , x; fscanf ( f , "%d%d%d" , &i , &j , &x ) == 3 && ( i || j || x ); )
	{
		SampleMap[i - 1][j - 1] = x;
	}

	fclose ( f );
	return true;
}


int main ()
{
	int sampleMap[MAXM][MAXM] = { 0 };
	int n = 0;
	if (fillSampleMap ( sampleMap , n ))
	{
		int first=collectSample ( sampleMap , n );
		int second=collectSample ( sampleMap , n );
		printf ( "\nRob的2条行走路径取得的样本总价值最大为:%d" , first + second );
		//写入文件函数较简单不单独写一个函数
		FILE* f = fopen ( "D:\\学习\\大三上\\算法设计与分析\\实验四报告+附件\\output(1).TXT" , "w" );
		fprintf ( f , "%d" , first + second );
		fclose ( f );
	}
	return 0;
}

四、实验结果:
在这里插入图片描述

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值