互不侵犯KING
题意:
给一个
让你求最多可以部署多少支部队,使得任意两支部队之间无法互相攻击
思路:
状态压缩DP,我们把每一行的状态用二进制来表示,山地为1,平原为0;然后我们枚举每一行的状态,把符合左右两格互不影响的所有状态存入
状态设置:
我们设置
转移方程:
我们处理这一行时,首先要判断枚举到的某个状态是否在山上,如果没有山地,那么枚举上一行的状态,如果不在山地,且不与本行冲突,那么枚举上两行的状态,如果不在山上,且不与本行冲突,不与上一行冲突,那么就可以进行状态转移。
初始化细节提示:
初始化时,我们首先要存所有满足条件的状态的炮兵的数量,以及满足条件的状态,然后我们预处理第二行即可。
代码:
/*
__builtin_popcount = int
__builtin_popcountl = long int
__builtin_popcountll = long long
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod= 998244353;
int n,m,f[110][1ll<<10][1ll<<10],cnt,st[1ll<<10],num[1ll<<10],ans;
int a[110];
void init(){
for (int s = 0; s <(1ll<<m) ; ++s) {
if(!(s&(s<<1ll))&&!(s&(s<<2ll))){
st[++cnt]=s;
num[cnt]=__builtin_popcount(s);
}
}
}
void solve(){
cin>>n>>m;
for (int i = 1; i <=n ; ++i) {
for (int j = 1; j <=m ; ++j) {
char s;
cin>>s;
if(s=='H')a[i]+=1ll<<(j-1);
}
}
init();
for (int i = 1; i <=cnt ; ++i) {
for (int j = 1; j <=cnt ; ++j) {
if(!(st[i]&st[j])&&!(st[i]&a[2])&&!(st[j]&a[1])){
f[2][i][j]=num[i]+num[j];
}
}
}
///f[i][j][k]表示第i行成立时,上一行是j状态,上两行是k状态的方案数。
for (int i = 3; i <=n ; ++i) {
for (int j = 1; j <=cnt ; ++j) {
if(!(st[j]&a[i])){
for (int lfirst = 1; lfirst <=cnt ; ++lfirst) {
if(!(st[lfirst]&a[i-1])&&!(st[lfirst]&st[j])){
for (int lsecond = 1; lsecond <=cnt ; ++lsecond) {
if(!(st[lsecond]&a[i-2])&&!(st[lsecond]&st[lfirst])&&!(st[lsecond]&st[j])){
f[i][j][lfirst]=max(f[i][j][lfirst],f[i-1][lfirst][lsecond]+num[j]);
ans= max(ans,f[i][j][lfirst]);
}
}
}
}
}
}
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t=1;
//cin>>t;
while (t--)solve();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】