洛谷 P1123 取数游戏
直接看代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
int ans,sum;
int a[9][9];
int vis[9][9];
int xx[] = {1,1,1,0,0,-1,-1,-1}; //寻找某点周围的点坐标
int yy[] = {1,0,-1,1,-1,1,0,-1};
void dfs(int x,int y)
{
if(y==m+1) //如果行已经搜索完了
{
dfs(x+1,1); //就搜索列
return;
}
if(x==n+1) //列也完成搜索后 就代表一次取数完成
{
ans = max(ans,sum); //比较这次得到的结果和最大值ans之间的关系 选择最大的
return;
}
dfs(x,y+1); // 先按行往下加 不选这一行
if(vis[x][y]==0) //选这一行且这一个数没有被标记 四周的数没有被取过
{
sum += a[x][y]; //加值
for(int i=0;i<8;i++) //标记周围点
{
if(x+xx[i]>=1&&x+xx[i]<=n&&y+yy[i]>=1&&y+yy[i]<=m)
++ vis[x+xx[i]][y+yy[i]]; //这里必须用++ 如果在它的附近选了两个或两个以上的数的话就要被标记相应的次数次
// 如果用 =1 就会导致在其中某个数溯洄的时候,这三个标记都会消失
}
dfs(x,y+1); //搜索下一行
for(int i=0;i<8;i++) //溯洄
{
if(x+xx[i]>=1&&x+xx[i]<=n&&y+yy[i]>=1&&y+yy[i]<=m)
-- vis[x+xx[i]][y+yy[i]]; //同理这里必须是--,一个数溯洄只能清除自己的标记,不能影响其他数的标记
}
sum -= a[x][y]; //溯洄值
}
}
int main()
{
int t;
cin>>t;
for(int i=1;i<=t;i++)
{
sum = 0;
ans = 0;
cin>>n>>m;
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis)); //每次开始前清0
for(int j=1;j<=n;j++)
{
for(int k=1;k<=m;k++)
cin>>a[j][k];
}
dfs(1,1); //从(1,1)开始搜索
cout<<ans<<endl;
}
return 0;
}
感觉这个题,是深搜,但是我想不到这种方法先遍历行再遍历列,而且感觉中间的给点标记是标记次数,感觉还挺容易错的
最近在刷洛谷的题,感觉稍微难一点的题,我都写不出来,这个也是参考了题解里面的答案写的,感觉写的真好,我怎么都想不出来,希望自己能记住吧,加油加油