取数游戏

题目描述

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

输入格式

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

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

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

输出格式

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

输入输出样例

输入 #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

说明/提示

对于第1组数据,取数方式如下:

[67] 75 63 10

29 29 [92] 14

[21] 68 71 56

8 67 [91] 25

对于20\%20%的数据,N, M≤3N,M3;

对于40\%40%的数据,N,M≤4N,M4;

对于60\%60%的数据,N, M≤5N,M5;

对于100\%100%的数据,N, M≤6,T≤20N,M6,T20。

 

这一题每个数是否选择会影响后面的选择情况,所以需要用一个数组来保存 所以状态为当前选到那个数,之前选的数的和以及之前每个数是否选了 之后直接搜索即可。尽管复杂度较高,但因为存在大量的不合法情况所以可以通过 时间复杂度为O(2nm)

 

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

int T,n,m,a[10][10],jishu,use[100][100];
void DFS(int x,int y,int z)//x,y为当前搜索到的点
{
    if(x>n)//搜索整个矩阵
    {
        jishu=max(jishu,z);
        return ;
    }
    int xx=x,yy=y+1;//下一个点
    if(yy>m)//搜索下一行
    {
        xx++;
        yy=1;
    }
    if(!use[x-1][y]&&!use[x][y-1]&&!use[x-1][y-1]&&!use[x-1][y+1])//选择这个点
    {
        use[x][y]=1;
        DFS(xx,yy,z+a[x][y]);
        use[x][y]=0;
    }
    DFS(xx,yy,z);//不选这个点
}
int main()
{
    int T;
    cin>>T;
    while(T--) 
    {
        jishu=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];
            }   
        }
        DFS(1,0,0);
        cout<<jishu<<endl;
    }

    return 0;

 

posted @ 2019-07-13 22:23  魂兮龙游  阅读(450)  评论(0编辑  收藏  举报