12.割地取田

news/发布时间2024/5/15 15:29:23

先梳理这道题的过程:尝试这个矩阵的所有可行取法,然后选择其中sum最大的一种。

这道题应该属于回溯法的范畴,我使用了一个递归函数search,这个search本质上是一种dfs方法。

首先需要两个数组:vl[8][8](vl表示value,存放每个田地的预期产出)和av[8][8](av表示available,存放判断每个田地能否选择的数字,若为0则表示可以访问,若不为0则表示不能访问)

这里的size是8*8的原因是,我希望按照元素行列数(从1开始)而不是下标进行表示(从0开始),所以相比6,横竖都多留了一圈。

遍历逻辑:有一个当前访问位置(r,c),意为(row,column),这个位置从[1][1]开始遍历,逐行向右移动。若移动到一行末尾(c>M),则跳到下一行第一个位置。

每次移动当前位置会遇到两种情况:这个位置可以访问,则将位置的值vl[r][c]加到sum上,并将这个格子本身及其八邻域都加1表示禁止访问(通过操作av数组),访问位置向右移动两格(因为右边一格在当前格子的八邻域内,一定无法访问)。若不能,则向右移动一格。

返回条件:当一直逐行向右遍历到当前格子的行数大于总行数,即r>N时,停止遍历。把这个深度分支的sum与全局变量max比较,让max取较大的一个。返回,并将上一层的av恢复成1。

回溯:返回后,要将当前位置的八邻域恢复(减一),然后向右移动一格。(这个操作本质上是认为当前格子不能取。)

写了两个函数,tag和detag,分别负责把一个格子八邻域的可访问性加一或减一。

完整代码如下:

#include <stdio.h>
int N,M;
int max;
int vl[8][8];    //vl for values
int av[8][8];    //av for available
void tag(int r,int c){    //标记 av[r-1][c-1]++;    //左上 av[r-1][c]++;    //av[r-1][c+1]++;    //右上 av[r][c-1]++;    //av[r][c]++;        //自身 av[r][c+1]++;    //av[r+1][c-1]++;    //左下 av[r+1][c]++;    //av[r+1][c+1]++;    //右下 
}
void detag(int r,int c){    //去标记    //printf("detag\n");av[r-1][c-1]--;    //左上 av[r-1][c]--;    //av[r-1][c+1]--;    //右上 av[r][c-1]--;    //av[r][c]--;        //自身 av[r][c+1]--;    //av[r+1][c-1]--;    //左下 av[r+1][c]--;    //av[r+1][c+1]--;    //右下 
}
void print(){//使用这个函数打印每次递归的av矩阵。int i,j;printf(" \n");for(i=1;i<=N;i++){for(j=1;j<=M;j++)    printf("%d ",av[i][j]);    //初始化printf("\n");}
}void search(int r,int c,int sum){//print(); //使用这个函数打印每次递归的av矩阵。if(c>M){//遍历逻辑:逐行右移 r++;c=1;}if(r>N){//!!结束标志!! max= sum>max ? sum : max;return;}if(0==av[r][c]){//若该点可访问,更新sum,右移两格(右移一格肯定无法访问) 
        tag(r,c);search(r,c+2,sum+vl[r][c]); detag(r,c);}//若不可访问或已回溯,不更新sum,右移一格。 search(r,c+1,sum);}
int main(void){max=0;scanf("%d %d",&N,&M);int i,j;for(i=1;i<=N;i++)    for(j=1;j<=M;j++)    scanf("%d",&vl[i][j]);for(i=0;i<8;i++)    for(j=0;j<8;j++)    av[i][j]=0;    //初始化search(1,1,0);printf("%d\n",max);
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/82851787.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

Vue双向数据绑定原理-中

defineProperty方法 defineProperty除了可以动态修改/新增对象的属性以外, 还可以在修改/新增的时候给该属性添加get/set方法, 从而实现数据劫持。 defineProperty get/set方法特点 只要通过defineProperty给某个属性添加了get/set方法,那么以后只要获取这个属性的值就会自动调…

电影推荐

《混凝土乌托邦》 --韩国

Begin of PHP

打开直接就是一份php代码,分析代码发现需要闯关,一共有五关 直接用ai给我翻译一下Level 1: 用户需要提供名为 key1 和 key2 的GET参数。 这两个参数的内容不应相同,但它们的MD5哈希值应该相同。 如果条件满足,将设置变量 $flag1 为True,否则会显示 "nope, this is le…

java面试点

语法基础 关键字:final: 用于表示某个变量、方法或类是最终的,不能被修改或继承 super: 可用于调用父类的方法或者字段 synchronized: 用于指定多线程代码中的同步方法、变量或者代码块 transient: 修饰的字段不会被序列化 const 在 C语言中是声明常量的关键字,在 Java …

软件测试:功能测试-接口测试-自动化测试-性能测试-验收测试

软件测试的主要流程一、测试主要的四个阶段 1.测试计划设计阶段:产品立项之后,进行需求分析,需求评审,业务需求评级,绘制业务流程图。确定测试负责人,开始制定测试计划; 2.测试准备阶段:各成员编写测试用例、先小组内评审、后会议评审,测试样机和配件,测试工具。 3.测…

学信息系统项目管理师第4版系列13_立项管理

立项管理1. 项目立项管理包括 1.1. 项目建议与立项申请 1.2. 项目可行性研究 1.2.1. 初步可行性研究 1.2.2. 详细可行性研究 1.2.2.1. 不可缺少 1.2.2.1.1. 【高21上选21】 1.2.3. 可以依据项目的规模和繁简程度合二为一 1.3. 项目评估与决策 2. 立项申请 2.1. 项目建议书 2.1.…