• P1123 取数游戏(洛谷)


    题目描述

    一个N×M的由非负整数构成的数字矩阵,你需要在其中取出若干个数字,使得取出的任意两个数字不相邻(若一个数字在另外一个数字相邻8个格子中的一个即认为这两个数字相邻),求取出数字和最大是多少。

    输入格式

    第1行有一个正整数T,表示了有T组数据。

    对于每一组数据,第一行有两个正整数N和M,表示了数字矩阵为N行M列。

    接下来N行,每行M个非负整数,描述了这个数字矩阵。

    输出格式

    T行,每行一个非负整数,输出所求得的答案。

    输入输出样例

    输入 #1
    3
    4 4
    67 75 63 10
    29 29 92 14
    21 68 71 56
    8 67 91 25
    2 3
    87 70 85
    10 3 17
    3 3
    1 1 1
    1 99 1
    1 1 1

    输出 #1

    271
    172
    99

    解题思路:

      直接用dfs是会TLE的(因为我直接用只跑通了4个测试样例),平常dfs中我们会使用for循环来改变要访问元素四个上下左右的位置,但是在此题中,dfs中套上for就会TLE。因此需要有一个更高效的移动方法:在此处,我们默认每次移动都是y+1;当时当y>m超过当前列数时,我们设置y=1(第一列)和x+1。由此看来,这个移动是固定的,而且我们可以知道下一步它的具体位置,在此方法中能确保所有位置都遍历到。移动的终止条件是x>n超过行数时return。

      我们对于每一个位置都有取和不取值两种情况(这样就涵盖了所有情况组合),从第一个位置搜索:取和不取先各来一次dfs。在dfs中,到达某个元素时,他有两种状态:能取和不能取,对于能取的:则取一次,标记为1表示取过,在dfs; 然后回溯标记0,再不取其值直接dfs,对于不能取的(表示周围元素有被取过的): 直接dfs。

      注意点:在这里不应该找到某个位置,取其值后就立即把它周围的元素给标记了,这样会带来很高的复杂度。dfs(x,y,sum)表示的是访问到xy位置时的状态,而且此时是否相加的情况也处理好了。因此下面代码的思路应该是访问到某个元素后,先找到它下一个要移动的位置,再去判断该位置是否能取其值,若能则接下来有两个dfs,若不能接下来有一个dfs。

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 int n,m;
     6 int a[10][10]={0};
     7 int map[10][10]={0};
     8 
     9 int maxx=0;    //用来存放最大值
    10 
    11 
    12 void dfs(int x,int y,int sum){        //x代表行,y代表列  sum当前值
    13  
    14     maxx=max(maxx,sum);
    15     
    16     //有规则的移动 列数加1直到列数最大时,此时列数变为1,行数++
    17     int my=y+1;
    18     int mx=x;
    19     if(my>m){
    20         my=1;
    21         mx=x+1;
    22     } 
    23     if(mx>n)    return;        //递归终止条件 
    24     
    25     
    26     if(!map[mx-1][my-1]&&!map[mx][my-1]&&!map[mx+1][my-1]&&!map[mx-1][my]&&!map[mx+1][my]&&!map[mx-1][my+1]&&!map[mx][my+1]&&!map[mx+1][my+1]){
    27         map[mx][my]=1;
    28         dfs(mx,my,sum+a[mx][my]);
    29         map[mx][my]=0;
    30     }
    31     
    32     dfs(mx,my,sum);
    33     
    34     return;
    35 }
    36 int main(){
    37     int t;
    38     cin>>t;
    39     
    40     for(int i=1;i<=t;i++){
    41         n=m=0;
    42         cin>>n>>m;
    43         memset(a,0,sizeof(a));
    44         maxx=0;
    45         
    46         for(int i=1;i<=n;i++){
    47             for(int j=1;j<=m;j++){
    48                 cin>>a[i][j];
    49             }
    50         } 
    51 
    52         memset(map,0,sizeof(map));
    53         dfs(1,1,0);  //代表取当前第一个数
    54         memset(map,0,sizeof(map));
    55         map[1][1]=1;
    56         dfs(1,1,a[1][1]);  //代表不取当前第一个数
    57         cout<<maxx<<endl;
    58         
    59     }
    60     return 0;
    61 }
     
  • 相关阅读:
    nagios高可用性设置
    絮叨--接上篇
    絮叨一下最近的那些人那些事
    记录一个小有意思的改变路径的问题
    nagios-解决监控页面上的乱码
    唠叨唠叨最近
    nagios监控远程主机服务可能出现的问题
    nagios监控远程主机端口
    nagios监控linux设置
    絮叨絮叨看护机房之监控
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12549799.html
Copyright © 2020-2023  润新知