洛谷P2704 [NOI2001]炮兵阵地【状压DP】

时空限制 1000ms / 128MB

题目描述

司令部的将军们打算在NM的网格地图上部署他们的炮兵部队。一个NM的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:

在这里插入图片描述

如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。 现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

输入格式:

第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符(‘P’或者‘H’),中间没有空格。按顺序表示地图中每一行的数据。N≤100;M≤10。

输出格式:

仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。


题目分析

d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示考虑 i i i,且 i i i行状态为 j j j i − 1 i-1 i1行状态为 k k k能放置的最多数量
dp方程 d p [ i ] [ j ] [ k ] = m a x ( d p [ i − 1 ] [ k ] [ l ] + s u m ( j ) ) dp[i][j][k]=max(dp[i-1][k][l]+sum(j)) dp[i][j][k]=max(dp[i1][k][l]+sum(j))(状态 j , k , l j,k,l j,k,l都合法, s u m ( j ) sum(j) sum(j) j j j状态的炮兵数)

如果直接枚举状态更新复杂度为 O ( n ∗ ( 2 m ) 3 ) O(n*(2^m)^3) O(n(2m)3),显然无法承受
于是考虑先把每一行只考虑单行不考虑地形的所有和合法状态枚举出来(即只考虑一行内不互相攻击)
可以通过计算得出一行内这样的合法状态数不超过70
于是枚举状态的时间复杂度就大大降低

最后答案为 a n s = m a x ( d p [ n ] [ i ] [ j ] ) ans=max(dp[n][i][j]) ans=max(dp[n][i][j])


#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
#define lowbit(x) ((x)&(-x))

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}

const int N=110;
const int M=13;
int n,m;
int rem[N];
int st[1<<M],num[1<<M],cnt;
int dp[N][M*10][M*10],ans;
char ss[M];

int check(int x)
{
    if(((x<<1)&x)||((x>>1)&x)) return 0;
    if(((x<<2)&x)||((x>>2)&x)) return 0;
    return 1;
}

int qsum(int x)
{
    int res=0;
    for(int i=x;i>0;i-=lowbit(i)) res++;//用lowbit计算1的个数
    //for(int i=1;i<=15;++i)
    //if(x&(1<<i-1)) res++;
    return res;
}

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)
    {
    	scanf("%s",&ss);
    	for(int j=0;j<m;++j)
    	if(ss[j]=='H') rem[i]|=1<<j;
    }
    
    for(int i=0;i<=(1<<m)-1;++i)//枚举一行内不考虑地形的合法状态
    if(check(i)){
        st[++cnt]=i;
        num[cnt]=qsum(i);
    }
    
    memset(dp,-1,sizeof(dp));
    for(int i=1;i<=cnt;++i)
    if(!(st[i]&rem[1]))
    dp[1][i][1]=num[i];//初始化第1行状态为i,上一行状态为全0
    
    for(int i=2;i<=n;++i)
    for(int j=1;j<=cnt;++j)//第i行的状态
    if(!(st[j]&rem[i]))
    for(int k=1;k<=cnt;++k)//第i-1行的状态
    if(!(st[k]&rem[i-1])&&!(st[j]&st[k]))
    for(int l=1;l<=cnt;++l)//第i-2行的状态
    if(!(st[j]&st[l])&&!(st[l]&st[k])&&!(rem[i-2]&st[l])&&dp[i-1][k][l]!=-1)
    dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]);
    
    for(int i=1;i<=cnt;++i)
    for(int j=1;j<=cnt;++j)
    ans=max(ans,dp[n][i][j]);
    
    printf("%d",ans);
    return 0;
}

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值