华师一附中OI组
标题:
P1123 取数游戏
[打印本页]
作者:
admin
时间:
2018-5-11 10:50
标题:
P1123 取数游戏
https://www.luogu.org/problemnew/show/P1123
题目描述
一个N×M的由非负整数构成的数字矩阵,你需要在其中取出若干个数字,使得取出的任意两个数字不相邻(若一个数字在另外一个数字相邻8个格子中的一个即认为这两个数字相邻),求取出数字和最大是多少。
输入输出格式
输入格式:
输入第1行有一个正整数T,表示了有T组数据。
对于每一组数据,第1行有两个正整数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
说明
对于第1组数据,取数方式如下:
[67] 75 63 10
29 29 [92] 14
[21] 68 71 56
8 67 [91] 25
对于20%的数据,N, M≤3;
对于40%的数据,N, M≤4;
对于60%的数据,N, M≤5;
对于100%的数据,N, M≤6,T≤20。
作者:
黄煦喆
时间:
2018-5-13 21:53
#include<iostream>
#include<cstdio>
#include<cstring>
#define ri(x,a,b) for(register int x=a;x<=b;x++)
using namespace std;
int n,m,t,tx,ty,s;
int mp[7][7],b[7][7];
int dx[9]={0,0,1,1,1,0,-1,-1,-1};
int dy[9]={0,1,-1,0,1,-1,0,-1,1};
void ch(int x,int y,int sum)
{
if(x>m)s=max(s,sum);
else if(y>n)ch(x+1,1,sum);
else if(b[x][y])ch(x,y+1,sum);
else
{
ri(i,1,8)
{
tx=x+dx[i];
ty=y+dy[i];
b[tx][ty]++;
}
ch(x,y+1,sum+mp[x][y]);
ri(i,1,8)
{
tx=x+dx[i];
ty=y+dy[i];
b[tx][ty]--;
}
ch(x,y+1,sum);
}
}
int main()
{
//freopen("qu.in","r",stdin);
cin>>t;
while(t--)
{
s=0;
cin>>m>>n;
memset(mp,0,sizeof(mp));
memset(b,0,sizeof(b));
ri(i,1,m)
ri(j,1,n)
cin>>mp[i][j];
ch(1,1,0);
cout<<s<<endl;
}
return 0;
}
复制代码
作者:
lyc
时间:
2018-5-13 23:20
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[10][10];
int fx[10] = {1,1,1,0,0,-1,-1,-1};
int fy[10] = {1,0,-1,1,-1,0,1,-1};
int vis[10][10];
int ans = 0;
int n,m;
void dfs(int x, int y, int sum){
int nx = x;
int ny = y+1;
if(ny == m+1){
nx++;
ny = 1;
}
if(x == n+1){
ans = max(ans, sum);
return ;
}
if(vis[x][y] == 0){
vis[x][y] ++;
for(int i=0; i<7; i++)
vis[x+fx[i]][y+fy[i]] ++;
dfs(nx, ny, sum+a[x][y]);
for(int i=0; i<7; i++)
vis[x+fx[i]][y+fy[i]] --;
vis[x][y] --;
}
dfs(nx, ny, sum);
}
int main(){
int t;
cin>>t;
while(t--){
ans = 0;
memset(a, 0, sizeof(a));
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
cin>>a[i][j];
dfs(1, 1, 0);
cout<<ans<<endl;
}
return 0;
}
复制代码
作者:
张笑宇
时间:
2018-5-24 22:55
#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int a[15][15];
int dx[9]={0,1,1,1,0,0,-1,-1,-1};
int dy[9]={0,1,-1,0,-1,1,0,1,-1};
int can[15][15];
void DFS(int i,int j,int now)
{
if(j>m)
{
i++;
j=1;
}
if(i>n)
{
if(now>ans)ans=now;
return;
}
int k;
if(can[i][j]==0){
for(k=1;k<9;k++) can[i+dx[k]][j+dy[k]]++;
DFS(i,j+2,now+a[i][j]);
for(k=1;k<9;k++) can[i+dx[k]][j+dy[k]]--;
}
DFS(i,j+1,now);
}
int main(){
int t,i,j;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
ans=0;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++)scanf("%d",&a[i][j]);
}
memset(can,0,sizeof(can));
DFS(1,1,0);
cout<<ans<<endl;
}
return 0;
}{:3_41:}
复制代码
作者:
admin
时间:
2018-5-25 17:00
很好!此题有两种做法,一个是DFS,判断某个数字是否可被选,然后比较最大值。
第二种方法是状压DP,大家看看我的DFS程序
#include<iostream>
using namespace std;
int t,n,m;
int a[8][8];
int b[8][8]; ///这个表示i,j位置被几个已选数字控制了!!!!
int ans;
int nx[]= {0,-1,-1,-1,+0,+0,+1,+1,+1};
int ny[]= {0,-1,+0,+1,-1,+1,-1,+0,+1};
void dfs(int i,int sum)
{
int x,y,tx,ty,k;
if(i>n*m)
{
if(sum>ans) ans=sum;
}
else
{
x=(i-1)/m+1,y=(i-1)%m+1;
if(b[x][y]) dfs(i+1,sum);
else
{
for( k=1; k<=8; k++)
{
tx=x+nx[k],ty=y+ny[k];
if(tx<=n &&ty<=m &&tx>=1 && ty>=1) b[tx][ty]++;
}
dfs(i+1,sum+a[x][y]);
for( k=1; k<=8; k++)
{
tx=x+nx[k],ty=y+ny[k];
if(tx<=n &&ty<=m &&tx>=1 && ty>=1) b[tx][ty]--;
}
dfs(i+1,sum);
}
}
}
int main()
{
cin>>t;
while(t--)
{
ans=-1;
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
cin>>a[i][j];
b[i][j]=0;
}
dfs(1,0);
cout<<ans<<endl;
}
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2