TLE了,哪位大佬帮我优化一下

P2704 [NOI2001] 炮兵阵地

Belarus @ 2019-08-24 15:50:04

#include<bits/stdc++.h>
using namespace std;
const int maxn=102,maxm=11;
int n,m,a[maxn],f[3][(1<<maxm)-1][(1<<maxm)-1],ans;
inline int count(int x){
    int cnt=0;
    for(int i=m-1;i>=0;i--) if((x>>i)&1) cnt++;
    return cnt;
}
inline bool valid(int row,int x){
    if(x&(x>>1)) return false;
    if(x&(x>>2)) return false;
    if(x&(x<<1)) return false;
    if(x&(x<<2)) return false;
    else for(int i=m-1;i>=0;i--){
        if(((x>>i)&1)&&(!((a[row]>>i)&1)))
         return false;
    }
    return true;
}
int main(){
    ios::sync_with_stdio(0);
    memset(f,-0x3f,sizeof(f));
    cin>>n>>m;
    char c;
    for(int i=1;i<=n;i++)
     for(int j=0;j<m;j++){
        cin>>c;
        while(c!='P' && c!='H') 
         cin>>c;
        if(c=='P') a[i]|=(1<<j);
     }
    f[0][0][0]=0;
    for(int j=0;j<(1<<m);j++)
     if(valid(1,j))
      f[1][j][0]=count(j);
    for(int i=2;i<=n;i++)
     for(int j=0;j<(1<<m);j++)
      if(valid(i,j))
       for(int k=0;k<(1<<m);k++)
        if((k&j)==0)
         if(valid(i-1,k))
          for(int l=0;l<(1<<m);l++)
           if((j&l)==0) 
            f[i%3][j][k]=max(f[i%3][j][k],f[(i-1)%3][k][l]+count(j));
    for(int j=0;j<(1<<m);j++)
     if(valid(n,j))
      for(int k=0;k<(1<<m);k++)
       if((k&j)==0)
        if(valid(n-1,k))
         ans=max(ans,f[n%3][j][k]);
    cout<<ans;
    return 0;
}

by kcn999 @ 2019-08-24 15:56:25

@Charleyxiao 预处理可行方案


by Belarus @ 2019-08-24 15:57:32

@kcn999 试过了,更慢(用递归写的)


by kcn999 @ 2019-08-24 15:57:40

也就是先把所有valid返回值为true的状态记录下来,然后再dp。


by 小小小朋友 @ 2019-08-24 15:57:55

这什么玩意儿……


by kcn999 @ 2019-08-24 15:58:26

@Charleyxiao 不是直接枚举就好了嘛,问什么要递归。。。


by End_donkey @ 2019-08-24 15:58:34

预处理再判断


by 小小小朋友 @ 2019-08-24 15:58:34

楼上的楼上正解


by Belarus @ 2019-08-24 16:00:41

@kcn999 谢谢


by kcn999 @ 2019-08-24 16:03:50

@Charleyxiao 好吧,其实我说的不是很清楚。先预处理出对于每一行,不考虑其他行的影响,只看当前行内是否可行的所有状态,然后dp的时候再判断是否在其他行的影响下不可行


by 吃饭且睡觉66 @ 2019-08-24 16:16:35

开o2试试


| 下一页