题解:P2704 [NOI2001] 炮兵阵地 状压dp

第一次状压的话建议先做:P1896 [SCOI2005] 互不侵犯

题目链接:P2704 [NOI2001] 炮兵阵地

题目要点如下:

  1. 每个炮兵会打到上下两行,左右各两格的队友

  2. 有地形限制,山上不能放炮兵

考虑状态定义:

第一维:由于会影响上下两行,所以要以两为单位来规划。

第二维:要枚举与当前双行状态相容的上面的(也就是第i-2和i-1行的)双行状态,所以要把当前行的状态记录下来~~(这不废话~~

所以状态表示:

f[i][j]表示(i与i+1行)状态为j时,能发下的最多炮兵个数

那么方程也就很简单了,只要找到与最大的与当前状态相容的f[i-2][k],加上当前状态的炮兵个数就行了:

f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i − 2 ] [ k ] ) + n u m [ j ] f[i][j]=max(f[i][j],f[i-2][k])+num[j] f[i][j]=max(f[i][j],f[i2][k])+num[j]

预处理:

  1. 穷举出单行合法状态

  2. 用单行合法状态穷举出双行合法状态

  3. 处理出双行的合法状态的后继双行合法状态

  4. (处理出双行合法状态的后继单行合法状态)

dp过程:

  1. 将第一行和第二行的状态初始化(与地形不相容的continue)

  2. 从第三行开始dp,枚举行

  3. 枚举当前行的状态(与地形不相容的continue)

  4. 枚举与当前行相容的状态(作为i-2与i-1的状态)

  5. 转移

由状态定义可知,max(f[n-1][i])即为所求

你是不是忘了n%2==1的情况了…

所以如果是奇数行的话,dp到第n-2和n-1行就停,最后单独dp一行

一些细枝末节的地方可以看看代码注释

#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
using namespace std;
int n,m;
char a[120][10];
int num1[70];int cnt1;
int num2[2200];int cnt2;
int lf[120];
vector<int> st1;
vector<pii> st2;
vector<int> vt[2200];
vector<int> vt1[70];
ll f[120][
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值