0x21 剪枝

这一章真是心态崩,剪枝太玄学啦,特别是那个搜索顺序我靠真的。。。

poj1011 枚举答案,搜索记录当前到第几根木棒。 剪枝:1、从大到小排序 2、排除等效,这个感觉还行,就是木棒按大小顺序进去,去除顺序不同的相同的情况,相同的木棒也是不用管的。  好的前面这些都可以想,关键是第三个,拼接第一个失败就全部重来。这个真是没想到

#include
#include
#include
#include
#include
#include
using namespace std;

int n,L,C,c[110];
bool cmp(int x,int y){return x>y;}
bool v[110];
bool dfs(int k,int len,int last)
{
    if(k==C+1)return true;
    if(len==L)return dfs(k+1,0,0);
    
    int fail=0;
    for(int i=last+1;i<=n;i++)
    {
        if(v[i]==false&&len+c[i]<=L&&c[i]!=fail)
        {
            v[i]=true;
            if(dfs(k,len+c[i],i))return true;
            v[i]=false;
            fail=c[i];
            if(len==0)return false;
        }
    }
    return false;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)break;
        
        int sum=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&c[i]), sum+=c[i];
        sort(c+1,c+n+1,cmp);
        
        int mmin=2147483647;
        for(int i=1;i*i<=sum;i++)
            if(sum%i==0)
            {
                if(i<mmin)
                {
                    L=i, C=sum/i;
                    memset(v,false,sizeof(v));
                    if(dfs(1,0,0)==true)mmin=min(mmin,i);
                }
                if(sum/isum)
                {
                    L=sum/i, C=i;
                    memset(v,false,sizeof(v));
                    if(dfs(1,0,0)==true)mmin=min(mmin,sum/i);
                }
            }
        printf("%d\n",mmin);
    }
    return 0;
}
poj1011

poj1190 这题简直就是剪枝的代表作了。。。我可以算是想出了1.5+2??个trick,但是这题整整五个剪枝啊!!!

1、大小,看到这个我都快条件反射了,管他有的没的倒序就是没错的

2、上下界,这个我想得还要复杂一点,导致有点难算,lyd就很暴力了直接开根

3、4、对于体积和表面积,到达目标的最小花费+当前花费比限制、当前最小花费大,那么就剪掉。我纠结了一会为啥一个叫可行性剪枝一个叫最优性剪枝,是因为体积是确定的而表面积是要求的

5、最***玄学的就是这个不等式了,上面全部的体积可以表示成sigema(1~dep-1)h[i]*r[i]^2,表面积就是2*sigema(1~dep-1)h[i]*r[i], 假设当前已经的体积为V

2*sigema(1~dep-1)h[i]*r[i] = 2/r[dep]*sigema(1~dep-1)h[i]*r[i]*r[dep] >= 2/r[dep]*sigema(1~dep-1)h[i]*r[i]*r[i] = 2*(N-V)/r[dep] 这个时候又可以判表面积。。。

#include
#include
#include
#include
#include
#include
using namespace std;

int N,m,mmin,r[11000],h[11000];
int minV[30],minS[30];
void dfs(int k,int V,int S)
{
    if(minV[k]+V>N)return ;
    if(minS[k]+S>mmin)return ;
    if(2*(N-V)/r[k+1]+S>mmin)return ;
    if(k==0)
    {
        if(minV[k]+V==N)mmin=min(mmin,S);
        return ;
    }
    
    int Rli=min( int(sqrt(double(N-V+1))) , r[k+1]-1 );
    for(int R=Rli;R>=k;R--)
    {
        int Hli=min( (N-V)/(R*R) , h[k+1]-1 );
        for(int H=Hli;H>=k;H--)
        {
            r[k]=R;h[k]=H;
            dfs(k-1,V+R*R*H,S+2*R*H+((k==m)?R*R:0));
        }
    }
}
int main()
{
    scanf("%d%d",&N,&m);
    for(int i=1;i<=m;i++)
        minV[i]=i*i*i+minV[i-1], minS[i]=2*i*i+minS[i-1];
    
    mmin=2147483647;
    r[m+1]=h[m+1]=2147483647;
    dfs(m,0,0);
    printf("%d\n",mmin);
    return 0;
}
poj1190

poj3076 状压,判点,判字母,绝望,留坟

#include
#include
#include
#include
#include
#include
#include
using namespace std;

int cnt;
char ss[20][20],sc[310][20][20];
bitset<16>mp[20][20],tt[310][20][20],ts[310][20][20];
void init()
{            
    memset(mp,0,sizeof(mp));
    for(int j=1;j<=16;j++)//
    {
        int zt=0;
        for(int i=1;i<=16;i++)
            if(ss[i][j]!='-')
                zt|=(1<<(ss[i][j]-'A'));
        for(int i=1;i<=16;i++) mp[i][j]|=zt;
    }
    for(int i=1;i<=16;i++)//
    {
        int zt=0;
        for(int j=1;j<=16;j++)
            if(ss[i][j]!='-') 
                zt|=(1<<(ss[i][j]-'A'));
        for(int j=1;j<=16;j++) mp[i][j]|=zt;
    }
    for(int i=1;i<=16;i+=4)
        for(int j=1;j<=16;j+=4)
        {
            int zt=0;
            for(int k=1;k<=4;k++)
                for(int l=1;l<=4;l++)
                    if(ss[i+k-1][j+l-1]!='-')
                        zt|=(1<<(ss[i+k-1][j+l-1]-'A'));
            for(int k=1;k<=4;k++)
                for(int l=1;l<=4;l++)
                        mp[i+k-1][j+l-1]|=zt;
        }
        
    cnt=0;
    for(int i=1;i<=16;i++)
        for(int j=1;j<=16;j++)
        {
            if(ss[i][j]=='-')cnt++;
            mp[i][j].flip();
        }
}

bitset<16>p;bool v[16];
bool check()
{
    for(int i=1;i<=16;i++)
        for(int j=1;j<=16;j++)
            if(mp[i][j]==0&&ss[i][j]=='-')return false;
    
    for(int i=1;i<=16;i++)
    {
        p.reset();memset(v,false,sizeof(v));
        for(int j=1;j<=16;j++)
        {
            if(ss[i][j]!='-')v[ss[i][j]-'A']=true;
            else p|=mp[i][j];
        }
        for(int o=0;o<=15;o++)
            if(p[o]==0&&v[o]==false)return false;
    }
    for(int j=1;j<=16;j++)
    {
        p.reset();
        for(int i=1;i<=16;i++)
        {
            if(ss[i][j]!='-')v[ss[i][j]-'A']=true;
            else p|=mp[i][j];
        }
        for(int o=0;o<=15;o++)
            if(p[o]==0&&v[o]==false)return false;
    }
    for(int i=1;i<=16;i+=4)
        for(int j=1;j<=16;j+=4)
        {
            p.reset();memset(v,false,sizeof(v));
            for(int k=1;k<=4;k++)
                for(int l=1;l<=4;l++)
                {
                    if(ss[i+k-1][j+l-1]!='-')v[ss[i+k-1][j+l-1]-'A']=true;
                    else p|=mp[i+k-1][j+l-1];
                }
        for(int o=0;o<=15;o++)
            if(p[o]==0&&v[o]==false)return false;
        }
    return true;
}
void influence(int x,int y)
{
    int o=ss[x][y]-'A';
    for(int j=1;j<=16;j++)mp[x][j][o]=0;
    for(int i=1;i<=16;i++)mp[i][y][o]=0;
    
    int i=((x-1)/4)*4+1,j=((y-1)/4)*4+1;
    for(int k=1;k<=4;k++)
        for(int l=1;l<=4;l++)
            mp[i+k-1][j+l-1][o]=0;
}
bool bk;
void dfs(int k,int dep)
{
    if(bk==true)return ;
        
    memcpy(ts[dep],mp,sizeof(ts[dep]));
    memcpy(sc[dep],ss,sizeof(sc[dep]));
    bool qwq=true;
    while(qwq)
    {
        qwq=false;
        for(int i=1;i<=16;i++)
            for(int j=1;j<=16;j++)
            {
                if(ss[i][j]=='-'&&mp[i][j].count()==1)
                {
                    k--;qwq=true;
                    for(int o=0;o<=15;o++)
                        if(mp[i][j][o]==1)
                        {
                            ss[i][j]='A'+o;
                            influence(i,j);
                            break;
                        }
                }
            }
        for(int o=1;o<=16;o++)
        {
            for(int i=1;i<=16;i++)
            {
                int u=0,jj;
                for(int j=1;j<=16;j++)
                    if(mp[i][j][o]==1)
                    {
                        u++;jj=j;
                        if(u==2)break;
                    }
                if(u==1)
                {
                    ss[i][jj]='A'+o;
                    influence(i,jj);
                }
            }
            for(int j=1;j<=16;j++)
            {
                int u=0,ii;
                for(int i=1;i<=16;i++)
                    if(mp[i][j][o]==1)
                    {
                        u++;ii=i;
                        if(u==2)break;
                    }
                if(u==1)
                {
                    ss[ii][j]='A'+o;
                    influence(ii,j);
                }
            }
            for(int i=1;i<=16;i+=4)
                for(int j=1;j<=16;j+=4)
                {
                    int u=0,ii,jj;
                    for(int k=1;k<=4;k++)
                        for(int l=1;l<=4;l++)
                        {
                            if(mp[i+k-1][j+l-1][o]==1)
                            {
                                u++;ii=i;jj=j;
                                if(u==2)break;
                            }
                        }
                    if(u==1)
                    {
                        ss[ii][jj]='A'+o;
                        influence(ii,jj);
                    }
                }
        }
    }//必定赋值 
    if(!check())
    {
        memcpy(mp,ts[dep],sizeof(mp));
        memcpy(ss,sc[dep],sizeof(ss));
        return ;
    }
    
    if(k==0)
    {
        bk=true;
        for(int i=1;i<=16;i++)
        {
            for(int j=1;j<=16;j++)printf("%c",ss[i][j]);
            printf("\n");
        }
        return ;
    }
    
    int cc=999999,nx,ny;
    for(int i=1;i<=16;i++)
        for(int j=1;j<=16;j++)
            if(ss[i][j]=='-'&&mp[i][j].count()<cc)
            {
                cc=mp[i][j].count();
                nx=i,ny=j;
            }
    for(int o=0;o<=15;o++)
        if(mp[nx][ny][o]==1)
        {
            memcpy(tt[dep],mp,sizeof(tt[dep]));
            ss[nx][ny]='A'+o;
            
            influence(nx,ny);
            if(check())
                dfs(k-1,dep+1);
            
            ss[nx][ny]='-';
            memcpy(mp,tt[dep],sizeof(mp));
        }
        
    memcpy(mp,ts[dep],sizeof(mp));
    memcpy(ss,sc[dep],sizeof(ss));
}
int main()
{
    for(int i=1;i<=16;i++)scanf("%s",ss[i]+1);
    init();
    
    bk=false;dfs(cnt,1);
    return 0;
}
poj3076(TLE)

 

转载于:https://www.cnblogs.com/AKCqhzdy/p/9270091.html

你可能感兴趣的:(0x21 剪枝)