列表

详情


NC16886. [NOI2001]炮兵阵地

描述

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

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

输入描述

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

输出描述

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

示例1

输入:

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

输出:

6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 60ms, 内存消耗: 24316K, 提交时间: 2022-08-11 12:02:52

#include<bits/stdc++.h>
using namespace std;
int n,m,dp[110][1<<10][1<<10];
int tot,z[1<<10];
int num[1<<10],ans;
int a[110];
char ch;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++)
	for(int j=1; j<=m; j++){
		cin>>ch;
		if(ch=='H')a[i]+=(1<<(j-1));
	}
	int nn=(1<<m)-1;
	for(int i=0; i<=nn; i++)
	if(!(i&(i<<1))&&!(i&i<<2)){
		tot++;
		z[tot]=i;
		int fl=i;
		while(fl>0)
		{
			if(fl&1)num[tot]++;
			fl>>=1;
		}
	}
	for(int i=1; i<=tot; i++)
	for(int j=1; j<=tot; j++)
	if(!(z[i]&z[j])&&!(z[i]&a[2])&&!(z[j]&a[1]))
    dp[2][i][j]=num[j]+num[i];
    for(int i=3;i<=n;i++)
    for(int j=1;j<=tot;j++)
    if(!(z[j]&a[i]))
    for(int k=1;k<=tot;k++)
    if(!(z[k]&a[i-1])&&!(z[k]&z[j]))
    for(int p=1;p<=tot;p++)
    if(!(z[p]&a[i-2])&&!(z[p]&z[k])&&!(z[p]&z[j]))
    {
        dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+num[j]);
        if(ans<dp[i][j][k])ans=dp[i][j][k];
    }
    printf("%d\n",ans);
    return 0;
}

C++ 解法, 执行用时: 249ms, 内存消耗: 876K, 提交时间: 2021-09-30 01:21:09

#include<bits/stdc++.h>
using namespace std;
int N, M;

int main() {
  cin >> N >> M;
  vector<string> G(N);
  for (auto &s: G) cin >> s;
  int sz = 1; for (int i = 0; i < M; i++) sz *= 3;
  vector<int> cur(sz);
  cur[0] = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0, bs = 1; j < M; j++, bs *= 3) {
      vector<int> nxt(sz);
      for (int s = 0; s < sz; s++) {
        int x = s / bs % 3;
        if (x == 0)  nxt[s] = max(cur[s], cur[s+bs]);
        else if (x == 1) nxt[s] = cur[s+bs];
        else if (x == 2 && G[i][j] == 'P') {
          if (j >= 1 &&  s/(bs/3)%3 == 2) continue;
          if (j >= 2 &&  s/(bs/9)%3 == 2) continue;
          nxt[s] = cur[s-bs-bs] + 1;
        }
      }
      cur = nxt;
    }
  }
  cout  << *max_element(cur.begin(), cur.end()) << endl;
}

上一题