样例输出5求调
查看原帖
样例输出5求调
999274
CNS_5t0_0r2楼主2024/7/6 11:32
#include<iostream>
#include<cstring>
using namespace std;
const int N = 109,M = 10,K = 109;
int n,m;
char c[N][M];
int valid_stat[K],count[K]/*第i个合法状态中1的个数*/,cnt;
int valid[N][K];//valid[i][j]:状态j在第i行是否合法
int dp[N][K][K];//dp[i][j][k]:第i行状态为j,第i - 1行状态为k的最多可摆放数量
int lowbit(int x){
	return x & (-x);
}
int popcount(int x){
	int ret = 0;
	for(;x;x -= lowbit(x))
		ret++;
	return ret;
}
bool check(int x){//状态x之间1的间隔是否不小于2
	while(lowbit(x) < x){
		int lb = lowbit(x);
		x -= lb;
		if(lowbit(x) / lb < 8)
			return false;
	}
	return true;
}
bool check2(int row,int x){
	for(int k = 0;k < m;k++)
		if(((x >> k) & 1) && c[row][k] == 'H')//在山地设置炮兵阵地,不合法
			return false;
	return true;
}
int main(){
	//ios::sync_with_stdio(false);
	//cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= n;i++)
		cin >> c[i];
	int tot = 1 << m;//状态总量
	
	for(int i = 0;i < tot;i++)
		if(check(i)){
			cnt++;
			valid_stat[cnt] = i;
			count[cnt] = popcount(i);
		}
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= cnt;j++){
			int stat = valid_stat[j];
			valid[i][j] = check2(i,stat);
		}
	}
	memset(dp,128,sizeof dp);
	dp[0][1][1] = 0;
	
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= cnt;j++){
			int stat1 = valid_stat[j];//第i行状态
			if(!valid[i][j])
				continue;
			for(int k = 1;k <= cnt;k++){
				int stat2 = valid_stat[k];//第i - 1行状态
				if(!valid[i - 1][k])
					continue;
				if(stat1 & stat2)
					continue;
				int Max = 0;
				for(int l = 1;l <= cnt;l++){
					int stat3 = valid_stat[l];
					if(stat1 & stat3)
						continue;
					Max = max(Max,dp[i - 1][k][l]);
				}
				dp[i][j][k] = Max + count[j];
			}
		}
	}
	int ans = 0;
	for(int j = 1;j <= cnt;j++){
		int stat1 = valid_stat[j];//第i行状态
		if(!valid[n][j])
			continue;
		for(int k = 1;k <= cnt;k++){
			int stat2 = valid_stat[k];//第i - 1行状态
			if(!valid[n - 1][k])
				continue;
			if(stat1 & stat2)
				continue;
			ans = max(ans,dp[n][j][k]);
		}
	}
	cout << ans;
	return 0;
}
2024/7/6 11:32
加载中...