P2704 [NOI2001] 炮兵阵地

第一份代码用状态作为dp数组下标,注意循环顺序:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
ll sd[101];
ll dp[101][1025][1025];
ll s[101],sum[1025],top,ans;
int main(){
//	for(int i=0;i<2000;i++) sum[i]=sum[i>>1]+(i&1);
//	for(int i=0;i<2000;i++) sum[i]=__builtin_popcount(i);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=0;j<m;j++){
			char now; cin>>now;
			if(now=='H')
			sd[i]|=1<<j;
		}
//		cout<<bitset<8>(sd[i])<<endl;
	}
//	m=10;
	for(int i=0;i<(1<<m);i++){
		if((i&(i>>1))|(i&(i>>2))) continue;
		s[++top]=i;
		sum[i]=__builtin_popcount(i);
//		cout<<bitset<10>(s[top])<<endl;
	}
//	cout<<top<<endl;
	for(int i=1;i<=top;i++){
		if(sd[1]&s[i]) continue;
		dp[1][s[i]][0]=sum[s[i]];
	}
	for(int i=2;i<=n;i++){
		for(int j=1;j<=top;j++){
			if(s[j]&sd[i]) continue;
			for(int k=1;k<=top;k++){
				if(s[k]&sd[i-1]) continue;
				if(s[k]&s[j]) continue;
				for(int u=1;u<=top;u++){
					if(s[u]&sd[i-2]) continue;
					if((s[u]&s[j])|(s[u]&s[k])) continue;
					dp[i][s[j]][s[k]]=max(dp[i][s[j]][s[k]],dp[i-1][s[k]][s[u]]+sum[s[j]]);
//					ans=max(ans,dp[i][s[j]][s[k]]);
				}
			}
		}
	}
		for(int j=1;j<=top;j++)
			for(int k=1;k<=top;k++){
				ans=max(ans, dp[n][s[j]][s[k]]);
			}
	cout<<ans<<endl;
    return 0;
}

第二份代码为了节约空间,用状态的下标作为dp数组下标,发现计算出来总是偏小
后来找到原来是初始化第一行的下标不对,修改后OK

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
ll sd[101];
ll dp[101][70][70];
ll s[101],sum[1025],top,ans;
int main(){
//	for(int i=0;i<2000;i++) sum[i]=sum[i>>1]+(i&1);
//	for(int i=0;i<2000;i++) sum[i]=__builtin_popcount(i);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=0;j<m;j++){
			char now; cin>>now;
			if(now=='H')
			sd[i]|=1<<j;
		}
//		cout<<bitset<8>(sd[i])<<endl;
	}
//	m=10;
	for(int i=0;i<(1<<m);i++){
		if((i&(i>>1))|(i&(i>>2))) continue;
		s[++top]=i;
		sum[i]=__builtin_popcount(i);
//		cout<<bitset<10>(s[top])<<endl;
	}
//	cout<<top<<endl;
	for(int i=1;i<=top;i++){
		if(sd[1]&s[i]) continue;
//		dp[1][i][0]=sum[s[i]];// 这是错的,最后一维不能是0 ,要改为1,因为我们从1开始存储 
		dp[1][i][1]=sum[s[i]];//
	}
	for(int i=2;i<=n;i++){
		for(int j=1;j<=top;j++){
			if(s[j]&sd[i]) continue;
			for(int k=1;k<=top;k++){
				if(s[k]&sd[i-1]) continue;
				if(s[k]&s[j]) continue;
				for(int u=1;u<=top;u++){
					if(s[u]&sd[i-2]) continue;
					if((s[u]&s[j])|(s[u]&s[k])) continue;
					dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][u]+sum[s[j]]);
//					ans=max(ans,dp[i][s[j]][s[k]]);
				}
			}
		}
	}
		for(int j=1;j<=top;j++)
			for(int k=1;k<=top;k++){
				ans=max(ans, dp[n][j][k]);
			}
	cout<<ans<<endl;
    return 0;
}
posted @ 2025-09-07 15:48  katago  阅读(9)  评论(0)    收藏  举报