CodeForces 111 C.Petya and Spiders(状压DP)

本文探讨了在一个n×m的矩阵中,每个位置有一只蜘蛛,每秒蜘蛛会向上下左右移动一步或待在原地的问题。目标是计算一秒后没有蜘蛛的位置数量的最大值。通过动态规划算法,详细解释了如何找到最优解,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

给出一个n×mn×m的矩阵,每个位置有一只蜘蛛,每秒蜘蛛会向上下左右移动一步或者待在原地不动,问一秒后没有蜘蛛的位置数量最大值

Input

两个整数n,m(1n,m,nm40)n,m(1≤n,m,n⋅m≤40)

Output

输出没有蜘蛛位置数量最大值

Sample Input

1 1

Sample Output

0

Solution

假设n<mn<m,以nn01表示一列蜘蛛的存在状态,以dp[i][y][z]dp[i][y][z]表示第ii列蜘蛛状态为y,第i+1i+1列蜘蛛状态为zz时无蜘蛛位置最大值,下面考虑找到合法的第i1列蜘蛛状态xx,由于第i1,i+1列蜘蛛状态可以往其他列走,故只要x,y,zx,y,z这相邻三列的状态能够满足让yy也即第i列蜘蛛状态合法即可,第ii列蜘蛛要么左移、不动或右移形成状态x,y,z,要么上下移动形成状态y>>1,y<<1y>>1,y<<1,也即只要x,y>>1,y,y<<1,zx,y>>1,y,y<<1,z这五个状态中每位都至少有一个11,那么x,y,z即为合法的相邻三列状态,进而有转移

dp[i][y][z]=max(dp[i][y][z],dp[i1][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状态中0的个数,最后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;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值