求助,代码里有详细注释,调了很久只过了第一个和第三个点 其他Wa了,谢谢大家

P2704 [NOI2001] 炮兵阵地

Autonomier @ 2020-03-25 19:24:59


#include<bits/stdc++.h>
//用了状态压缩的思想,但只过了第一个和第三个测试点,其他都是WrongAnswer 
using namespace std;
#define ll long long
#define maxn 10000000
inline int read()
{
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;
}
int n,m,res,dp[1000][1000][3],a[20],sum[1<<10+5];
//dp[i][j][k]表示前一行状态为sta[i],当前行状态为sta[j],k=当前行数%3(因为开三维数组会炸空间) 
int sta[1<<10+5];//存储可行状态 
char knd;
inline int cal(int x)
//统计每个二进制数中有几个一,就是放了几个兵 
{
    int cnt=0;
    while(x)
    {
        if(x&1)
            cnt++;
        x>>=1;
    //  cout<<7;
    }
    return cnt; 
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        //存储地图,平原为1,山地为0 
        {
            cin>>knd;
            a[i]<<=1;
            a[i]+=(knd=='P' ? 1:0);
        }
    }
    int k=0;
    for(int i=0;i<(1<<m);i++)
    //只考虑一行内的所有可行情况 
    {
        if(!(i&(i<<1))&&!(i&(i<<2))&&!(i&(i>>2))&&!(i&(i>>1)))
        {
            sum[++k]=cal(i);
            sta[k]=i;
        }
    }
    for(int i=1;i<=k;i++)
    //将dp数组第一行更新 
    {
        if((sta[i]&a[1])==sta[i])
        {
            dp[0][i][1]=sum[i];
        }
    }
    for(int j=1;j<=k;j++)
    {
        for(int i=1;i<=k;i++)
        //更新第二行 
        {
            if(((a[1]&sta[i])==sta[i])&&((a[2]&sta[j])==sta[j])&& !(sta[i]&sta[j]))
            {
                dp[i][j][2]=sum[i]+sum[j];
            }
        }
    }
    for(int i=3;i<=n;i++)
    //从第三行开,进行dp 
    {
        for(int j=1;j<=k;j++)//枚举上上行状态 
        {
                for(int l=1;l<=k;l++)//枚举上一行状态 
                {
                        for(int e=1;e<=k;e++)//枚举当前行状态 
                        {
                            if(((sta[j]&a[i-2])==sta[j])&&((sta[l]&a[i-1])==sta[l])&&((sta[e]&a[i])==sta[e])&& !(sta[j]&sta[l])&& !(sta[l]&sta[e])&& !(sta[j]&sta[e]))
                            //分别判断是否与地图相符,且上下行是否有冲突 
                            {
                                dp[l][e][i%3]=max(dp[l][e][i%3],dp[j][l][(i-1)%3]+sum[e]);
                            }   
                        }
                }
        }   
    }
    for(int i=1;i<=k;i++)
    {
        for(int j=1;j<=k;j++)
        {
            if(!(sta[i]&sta[j]))
            {
                res=max(res,dp[i][j][n%3]);//统计第n行答案,寻找最大值 
            }

        }
    }
    cout<<res<<endl;
    return 0;
}

by derta @ 2020-04-24 23:04:12

铜球


|