Description
给出一个n×mn×m的矩阵,每个位置有一只蜘蛛,每秒蜘蛛会向上下左右移动一步或者待在原地不动,问一秒后没有蜘蛛的位置数量最大值
Input
两个整数n,m(1≤n,m,n⋅m≤40)n,m(1≤n,m,n⋅m≤40)
Output
输出没有蜘蛛位置数量最大值
Sample Input
1 1
Sample Output
0
Solution
假设n<mn<m,以nn位表示一列蜘蛛的存在状态,以dp[i][y][z]dp[i][y][z]表示第ii列蜘蛛状态为,第i+1i+1列蜘蛛状态为zz时无蜘蛛位置最大值,下面考虑找到合法的第列蜘蛛状态xx,由于第列蜘蛛状态可以往其他列走,故只要x,y,zx,y,z这相邻三列的状态能够满足让yy也即第列蜘蛛状态合法即可,第ii列蜘蛛要么左移、不动或右移形成状态,要么上下移动形成状态y>>1,y<<1y>>1,y<<1,也即只要x,y>>1,y,y<<1,zx,y>>1,y,y<<1,z这五个状态中每位都至少有一个11,那么即为合法的相邻三列状态,进而有转移
dp[i][y][z]=max(dp[i][y][z],dp[i−1][x][y]+num[y])dp[i][y][z]=max(dp[i][y][z],dp[i−1][x][y]+num[y])
其中num[y]num[y]为yy状态中的个数,最后∑dp[m][i][0]∑dp[m][i][0]即为答案
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100001;
int n,m,N,dp[40][70][70],num[70];
bool check(int x,int y,int z)
{
int S=x|y|z|(y<<1)|(y>>1);
if((S&(N-1))==N-1)return 1;
return 0;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n>m)swap(n,m);
N=1<<n;
memset(dp,-1,sizeof(dp));
num[0]=0;
for(int i=1;i<N;i++)num[i]=num[i/2]+(i&1);
for(int i=0;i<N;i++)num[i]=n-num[i],dp[0][0][i]=0;
for(int i=1;i<=m;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
if(dp[i-1][j][k]!=-1)
for(int l=0;l<N;l++)
if(check(j,k,l))
dp[i][k][l]=max(dp[i][k][l],dp[i-1][j][k]+num[k]);
int ans=0;
for(int i=0;i<N;i++)ans=max(ans,dp[m][i][0]);
printf("%d\n",ans);
}
return 0;
}