题目描述
一个N×M的由非负整数构成的数字矩阵,你需要在其中取出若干个数字,使得取出的任意两个数字不相邻(若一个数字在另外一个数字相邻8个格子中的一个即认为这两个数字相邻),求取出数字和最大是多少。
输入格式
第1行有一个正整数T,表示了有T组数据。
对于每一组数据,第一行有两个正整数N和M,表示了数字矩阵为N行M列。
接下来N行,每行M个非负整数,描述了这个数字矩阵。
输出格式
T行,每行一个非负整数,输出所求得的答案。
此题目的思路比较简单,就是通过dfs把数相加的每一种可能都列举出来比较即可,每选择一个数就需要把他周围的八个数标记一下,切记此处标记用int数组不要用bool,因为同一个元素可能同时是两个不同的元素的“周围八个数之一”,所以用bool存储会还原现场会出问题。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,n,m,s=0;
int q[30][30]={0};//存储矩阵值
int vis[30][30]={0};//记录当前元素是否已经使用过亦或是已经使用过的元素周围的八个数
int px[8]={-1,0,1,-1,1,-1,0,1};
int py[8]={-1,-1,-1,0,0,1,1,1};//记录x和y的偏移量
void dfs(int x,int y,int sum)
{
if(y==m+1)//搜索到最后一列就换行
{
dfs(x+1,1,sum);
return;
}
if(x==n+1)//搜索到最后一行就停止
{
s=max(s,sum);//取最大值
return;
}
dfs(x,y+1,sum);//不加当前值
if(vis[x][y]==0)//加上当前值
{
for(int i=0;i<8;i++)
vis[x+px[i]][y+py[i]]++;
dfs(x,y+1,sum+q[x][y]);
for(int i=0;i<8;i++)
vis[x+px[i]][y+py[i]]--;//还原现场
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
memset(q,0,sizeof(s));
memset(vis,0,sizeof(vis));//每一次都要初始化数组
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>q[i][j];
s=0;
dfs(1,1,0);
cout<<s<<endl;
}
return 0;
}