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;
}

浙公网安备 33010602011771号