二维状压DP,不知道思路对不对

P2704 [NOI2001] 炮兵阵地

jpjpjpjp @ 2024-08-07 21:47:06

思路:每次枚举第i,i-1,i-2行的状态

如果合法,dp[i][s1]=max(dp[i-2][s3]+count(s2)+count(s1)

不确定思路对不对,写出来只有20pts

(当然也有可能是本蒟蒻码力不足...)

如果思路是错的,希望有dalao能够给小蒟蒻指示一下。 代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,maxst;
int mp[105],dp[105][2050];
bool check(int x,int i)
{
    if(mp[i]&x)return 0;
    if(x&(x>>1))return 0;
    if(x&(x>>2))return 0;
    return 1;
}
int lowbit(int x)
{
    return x&(-x);
}
int count(int x)
{
    int cnt=0;
    while(x>0)x-=lowbit(x),cnt++;
    return cnt;
}
signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        string x;
        cin>>x;
        for(int j=0;j<x.length();j++)
            if(x[j]=='H')mp[i]|=(1<<(x.length()-j-1));
    }
    maxst=(1<<m)-1;
    for(int s1=0;s1<=maxst;s1++){
        if(!check(s1,1))continue;
        dp[1][s1]=count(s1);
    }
    for(int s1=0;s1<=maxst;s1++){
        if(!check(s1,2))continue;
        int g=count(s1);
        for(int s2=0;s2<=maxst;s2++){
            if(!check(s2,1))continue;
            if(s1&s2)continue;
            dp[2][s1]=max(dp[2][s1],dp[1][s2]+g);
        }
    }
//  for(int i=1;i<=2;i++){
//      cout<<"i="<<i<<" ";
//      for(int j=0;j<=maxst;j++)cout<<dp[i][j]<<" ";
//      cout<<endl;
//  }
    for(int i=3;i<=n;i++){
        for(int s1=0;s1<=maxst;s1++){
            if(!check(s1,i))continue;
            for(int s2=0;s2<=maxst;s2++){
                if(!check(s2,i-1))continue;
                if(s1&s2)continue;
                for(int s3=0;s3<=maxst;s3++){
                    if(!check(s3,i-2))continue;
                    if((s2&s3)||(s1&s3))continue;
                    dp[i][s1]=max(dp[i][s1],dp[i-2][s3]+count(s2)+count(s1));
                }
            }
        }
//      cout<<"i="<<i<<" ";
//      for(int j=0;j<=maxst;j++)cout<<dp[i][j]<<" ";
//      cout<<endl;
    }
    int ans=0;
    for(int i=0;i<=maxst;i++)ans=max(ans,dp[n][i]);
    printf("%lld",ans);
    return 0;
}

by yedalong @ 2024-08-07 22:01:30

我用的是三维。

$ans$ 应为 $max(dp[n][i][j])$,由于数据大记得用滚动数组。 问题总结:$dp$ 数组没考虑 $(i-1)$行以及$(i-2)$ 行的状态

by yedalong @ 2024-08-07 22:09:19

@jpjpjpjp


by jpjpjpjp @ 2024-08-08 08:06:23

@yedalong 枚举第i-1行和第i-2行的状态的时候不就相当于把第i-1行和第i-2行的状态考虑进去了吗? 多记i-2这一维是因为第i-2层的状态也会影响第i层的状态,在转移时需确保第i-2层的状态合法 但是我更新dp[i]的时候我用的不是dp[i-1]而是dp[i-2], 这样转移的时候就不会出现第i-1行合法,第i-2行不合法的情况


by jpjpjpjp @ 2024-08-08 08:17:21

@yedalong 我明白了

在转移的时候我是直接用dp[i-2]+count(i-1行的状态)+count(i行的状态)

无法保证第i-1行的状态与第i-3行的状态不冲突,所以答案就会算多


by jpjpjpjp @ 2024-08-08 08:23:47

此贴结


|