• 搜索专题总结


    搜索专题总结

    第七章的例题做得差不多了,还有一道枚举二叉树和一道比较难的搜方块的没过,另外有一道火柴的用IDA*水过,并没有过大数据,由于这道可以用dancing links过,所以留着dancing links一坑。接下来总结下这章的收获,首先最重要的当然是不需要判重的高效率的IDA*以及估价函数的设计技巧;然后是bfs+hash写得更熟练了,如果hash需要erase那么就只能用指针版的,但是效率会很慢,否则就用数组版的。

    做搜索题的几个要点:

    1,估算最坏复杂度。

    2,寻找合适的剪枝策略,估计剪枝的效果,根据情况选择IDA*还是bfs,最坏复杂度高但剪枝效果明显的优先IDA*。

    3,想清楚代码的大致框架。

    4,想清楚代码实现困难的细节以及可能出错需要注意的地方。

    5,大胆快速的写吧。

    下面是第七章的例题:

    A题:

    输出所有的xxxxx / xxxxx =N

    只要枚举上面的数字就行了,复杂度<10^5,直接循环枚举。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000001;
    const double Pi=acos(-1.0);
    
    int n;
    int a,b;
    bool vis[maxn];
    bool has[20];
    
    bool check(int b)
    {
        MS0(has);
        REP(i,1,5){
            int x=b%10;b/=10;
            if(vis[x]||has[x]) return 0;
            has[x]=1;
        }
        return 1;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int st=1;
        while(cin>>n,n){
            if(!st) puts("");
            st=0;
            MS0(vis);
            a=0;
            bool flag=0;
            REP(i,0,9){
                vis[i]=1;
                a=a*10+i;
                REP(j,0,9){
                    if(vis[j]) continue;
                    vis[j]=1;
                    a=a*10+j;
                    REP(k,0,9){
                        if(vis[k]) continue;
                        vis[k]=1;
                        a=a*10+k;
                        REP(l,0,9){
                            if(vis[l]) continue;
                            vis[l]=1;
                            a=a*10+l;
                            REP(x,0,9){
                                if(vis[x]) continue;
                                vis[x]=1;
                                a=a*10+x;
                                if(a%n==0&&check(a/n)){
                                    flag=1;
                                    printf("%05d / %05d = %d
    ",a,a/n,n);
                                }
                                vis[x]=0;
                                a-=x;a/=10;
                            }
                            vis[l]=0;
                            a-=l;a/=10;
                        }
                        vis[k]=0;
                        a-=k;a/=10;
                    }
                    vis[j]=0;
                    a-=j;a/=10;
                }
                vis[i]=0;
                a-=i;a/=10;
            }
            if(!flag) printf("There are no solutions for %d.
    ",n);
        }
        return 0;
    }
    View Code

    B题:

    水题,暴力。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000001;
    const double Pi=acos(-1.0);
    
    int n;
    ll a[maxn];
    
    ll cal(int l,int r)
    {
        ll res=1;
        REP(i,l,r) res*=a[i];
        return res;
    }
    
    int main()
    {
        int casen=1;
        while(cin>>n){
            REP(i,1,n) scanf("%lld",&a[i]);
            ll ans=0;
            REP(l,1,n){
                REP(r,l,n){
                    ll tmp=cal(l,r);
                    ans=max(ans,tmp);
                }
            }
            printf("Case #%d: The maximum product is %lld.
    
    ",casen++,ans);
        }
        return 0;
    }
    View Code

    C题:

    水题,先确定下范围再枚举。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000001;
    const double Pi=acos(-1.0);
    
    ll k,x,y;
    struct St
    {
        ll x,y;
    };
    vector<St> ans;
    
    int main()
    {
        while(cin>>k){
            ans.clear();
            for(y=k+1;;y++){
                x=k*y/(y-k);
                if(x<y) break;
                if((k*y)%(y-k)==0){
                    x=k*y/(y-k);
                    if(x<y) break;
                    ans.push_back({x,y});
                }
            }
            printf("%d
    ",(int)ans.size());
            for(int i=0;i<ans.size();i++){
                printf("1/%lld = 1/%lld + 1/%lld
    ",k,ans[i].x,ans[i].y);
            }
        }
        return 0;
    }
    View Code

    D题:

    水题,dfs就行了。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000001;
    const double Pi=acos(-1.0);
    
    int n,a[maxn];
    bool vis[maxn],isprime[maxn];
    
    void getPrime()
    {
        memset(isprime,1,sizeof(isprime));
        isprime[1]=0;
        REP(i,2,maxn-1){
            if(!isprime[i]) continue;
            for(int j=i+i;j<maxn;j+=i) isprime[j]=0;
        }
    }
    
    void dfs(int cur)
    {
        if(cur>n){
            if(!isprime[a[n]+a[1]]) return;
            REP(i,1,n) printf("%d%c",a[i],i==n?'
    ':' ');
            return;
        }
        REP(i,1,n){
            if(!vis[i]&&isprime[a[cur-1]+i]){
                a[cur]=i;
                vis[i]=1;
                dfs(cur+1);
                vis[i]=0;
            }
        }
    }
    
    int main()
    {
        int casen=1;
        getPrime();
        int st=1;
        while(cin>>n){
            MS0(vis);
            if(!st) puts("");
            st=0;
            printf("Case %d:
    ",casen++);
            a[1]=1;
            vis[1]=1;
            dfs(2);
        }
        return 0;
    }
    View Code

    E题:困难的串。

    很经典的题,只要不断往后添加然后判断就行了,关键在于判断的复杂度,由于substr(0,l-1)是已经判断过的,所以只要判断后缀就行了。

    /// 19:43 2015/11/16
    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int n,L;
    int cur;
    bool flag;
    string ans;
    
    bool judge(string s)
    {
        int len=s.size();
        for(int i=1;i<=len/2;i++){
            //out<<s.substr(len-2*i,i)<<"_"<<s.substr(len-i,i)<<endl;
            if(s.substr(len-2*i,i)==s.substr(len-i,i)) return false;
        }
        return true;
    }
    
    void dfs(string s)
    {
        if(flag) return;
        if(cur==n){
            ans=s;flag=1;return;
        }
        cur++;
        REP(i,0,L-1){
            string t=s+char('A'+i);
            if(judge(t)) dfs(t);
        }
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(cin>>n>>L,(n||L)){
            cur=0;flag=0;
            dfs("");
            REP(i,0,(int)ans.size()-1){
                printf("%c",ans[i]);
                if(i%64==63&&i!=(int)ans.size()-1) printf("
    ");
                else if(i%4==3&&i!=(int)ans.size()-1) printf(" ");
            }
            printf("
    %d
    ",(int)ans.size());
        }
        return 0;
    }
    View Code

    F题:

    枚举排列就行了,复杂度能过,注意输入的处理。

    /// 20:34~ 2015/11/16
    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    char s[maxn];
    vector<int> G[maxn];
    int a[maxn],pos[maxn];
    int b[maxn],ans;
    int id[maxn],fid[maxn];
    int n;
    bool vis[maxn];
    
    void build()
    {
        REP(i,1,8) G[i].clear();
        memset(id,-1,sizeof(id));
        n=0;
        int len=strlen(s);
        for(int i=0;i<len;){
            int u=id[s[i]];
            if(u==-1) u=id[s[i]]=++n,fid[n]=s[i];
            int j;
            for(j=i+2;j<len;j++){
                if(s[j]==';') break;
                int v=id[s[j]];
                if(v==-1) v=id[s[j]]=++n,fid[n]=s[j];
                G[u].push_back(v);
                G[v].push_back(u);
            }
            i=j+1;
        }
    }
    
    void update()
    {
        REP(i,1,n) pos[a[i]]=i;
        int res=0;
        REP(u,1,n){
            for(int i=0;i<G[u].size();i++){
                int v=G[u][i];
                res=max(res,abs(pos[u]-pos[v]));
            }
        }
        if(res<ans){
            REP(i,1,n) b[i]=a[i];
            ans=res;
        }
        else if(res==ans){
            bool flag=0;
            REP(i,1,n){
                if(fid[a[i]]<fid[b[i]]){
                    flag=1;break;
                }
                else if(fid[a[i]]>fid[b[i]]) break;
            }
            if(flag){
                REP(i,1,n) b[i]=a[i];
            }
        }
    }
    
    void dfs(int cur,int now)
    {
        a[cur]=now;
        vis[now]=1;
        if(cur==n) update();
        REP(i,1,n) if(!vis[i]) dfs(cur+1,i);
        vis[now]=0;
    }
    
    void solve()
    {
        ans=INF;
        REP(i,1,n) dfs(1,i);
        REP(i,1,n) printf("%c ",fid[b[i]]);
        printf("-> %d
    ",ans);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%s",s)){
            if(strcmp(s,"#")==0) break;
            build();
            solve();
        }
        return 0;
    }
    View Code

    H题:

    倒水。bfs都可以,注意由于求的是倒水量最小而不是次数最少,所以bfs要用优先队列,IDA*似乎不太适合,因为倒水量的范围比较大。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=8000100;
    const int INF=(1<<29);
    
    int s[3],d;
    int ans,d_;
    bool vis[maxn];
    struct Node
    {
        int s[3];
        int step;
        friend bool operator<(Node A,Node B)
        {
            return A.step>B.step;
        }
        void debug()
        {
            printf("x=%2d y=%2d z=%2d step=%2d
    ",s[0],s[1],s[2],step);
        }
    };
    
    int st(Node u)
    {
        int res=0;
        REP(i,0,2) res=res*201+u.s[i];
        return res;
    }
    
    Node pop(Node u,int x,int y)
    {
        if(u.s[x]<=s[y]-u.s[y]){
            u.step+=u.s[x];
            u.s[y]+=u.s[x];
            u.s[x]=0;
            return u;
        }
        else{
            u.step+=s[y]-u.s[y];
            u.s[x]-=s[y]-u.s[y];
            u.s[y]=s[y];
            return u;
        }
    }
    
    void bfs()
    {
        MS0(vis);
        priority_queue<Node> q;
        Node ss={0,0,s[2],0};
        q.push(ss);
        vis[st(ss)]=1;
        ans=0;d_=0;
        while(!q.empty()){
            Node u=q.top();q.pop();
            ///u.debug();
            REP(i,0,2){
                if(u.s[i]>d_&&u.s[i]<=d){
                    d_=u.s[i];ans=u.step;
                }
            }
            if(d_==d) break;
            Node v;
            /// 1->2
            v=pop(u,0,1);
    
            if(!vis[st(v)]) q.push(v),vis[st(v)]=1;
            /// 1->3
            v=pop(u,0,2);
            if(!vis[st(v)]) q.push(v),vis[st(v)]=1;
            /// 2->1
            v=pop(u,1,0);
            if(!vis[st(v)]) q.push(v),vis[st(v)]=1;
            /// 2->3
            v=pop(u,1,2);
            if(!vis[st(v)]) q.push(v),vis[st(v)]=1;
            /// 3->1
            v=pop(u,2,0);//cout<<"01"<<" ";v.debug();
            if(!vis[st(v)]) q.push(v),vis[st(v)]=1;
            /// 3->2
            v=pop(u,2,1);
            if(!vis[st(v)]) q.push(v),vis[st(v)]=1;
        }
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%d%d%d%d",&s[0],&s[1],&s[2],&d);
            MS0(vis);
            bfs();
            printf("%d %d
    ",ans,d_);
        }
        return 0;
    }
    View Code

    I题:

    很经典的状态空间搜索问题,由于不可走的区域很多,所以重新建图以减小复杂度,这里判重很容易,直接bfs,当然IDA*也可以。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int w,h,m;
    char ch[20][20];
    vector<int> G[maxn];int n;
    struct Node
    {
        char c;
        int x;
        friend bool operator<(Node A,Node B)
        {
            return A.c<B.c;
        }
    };
    Node S[maxn],T[maxn];
    int id[20][20];
    int dx[]={-1,1,0,0};
    int dy[]={0,0,-1,1};
    bool vis[300][300][300];
    struct qNode
    {
        int x,y,z;
        int d;
    };
    
    bool jud(int x,int y,int z,int nx,int ny,int nz)
    {
        if(m==1) return 1;
        if(m==2){
            if(nx==ny) return 0;
            if(x==ny&&y==nx) return 0;
            return 1;
        }
        if(m==3){
            if(nx==ny||ny==nz||nz==nx) return 0;
            if(x==ny&&y==nx) return 0;
            if(y==nz&&z==ny) return 0;
            if(z==nx&&x==nz) return 0;
            return 1;
        }
    }
    
    int bfs()
    {
        MS0(vis);
        queue<qNode> q;
        qNode s={S[1].x,S[2].x,S[3].x,0};
        qNode t={T[1].x,T[2].x,T[3].x,0};
        q.push(s);
        vis[s.x][s.y][s.z]=1;
        while(!q.empty()){
            qNode u=q.front();q.pop();
            int x=u.x,y=u.y,z=u.z,d=u.d;
            if(x==t.x&&y==t.y&&z==t.z) return d;
            for(int i=0;i<G[x].size();i++){
                int nx=G[x][i];
                for(int j=0;j<G[y].size();j++){
                    int ny=G[y][j];
                    for(int k=0;k<G[z].size();k++){
                        int nz=G[z][k];
                        if(!vis[nx][ny][nz]&&jud(x,y,z,nx,ny,nz)){
                            q.push({nx,ny,nz,d+1});
                            vis[nx][ny][nz]=1;
                        }
                    }
                }
            }
        }
        return -1;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(cin>>w>>h>>m){
            if(w==0&&h==0&&m==0) break;
            gets(ch[0]);
            REP(i,1,h) gets(ch[i]+1);
            n=0;
            MS0(id);
            int ks=0,kt=0;
            MS0(S);MS0(T);
            REP(i,1,h){
                REP(j,1,w){
                    if(ch[i][j]!='#'){
                        id[i][j]=++n;
                        if(islower(ch[i][j])) S[++ks]={ch[i][j],n};
                        if(isupper(ch[i][j])) T[++kt]={ch[i][j],n};
                    }
                }
            }
            REP(i,0,maxn-1) G[i].clear();
            G[0].push_back(0);
            REP(i,1,h){
                REP(j,1,w){
                    int u=id[i][j];
                    if(!u) continue;
                    G[u].push_back(u);
                    REP(k,0,3){
                        int ni=i+dx[k],nj=j+dy[k];
                        int v=id[ni][nj];
                        if(!v) continue;
                        G[u].push_back(v);
                    }
                }
            }
            sort(S+1,S+m+1);sort(T+1,T+m+1);
            printf("%d
    ",bfs());
        }
        return 0;
    }
    View Code

    J题:剪纸问题。

    又是一道很经典的状态空间搜索问题。这里以每个元素的相对位置来设计的估价函数剪枝效果明显,所以用IDA*,效率非常高。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define PB push_back
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=2000100;
    const int INF=(1<<29);
    
    int n;
    struct Node
    {
        int a[11];
        void read()
        {
            REP(i,1,n) scanf("%d",&a[i]);
        }
    };Node s;
    
    bool judge(Node s)
    {
        REP(i,1,n){
            if(s.a[i]!=i) return 0;
        }
        return 1;
    }
    
    Node cut(Node s,int l,int r,int L,int R)
    {
        Node res=s;
        REP(i,0,R-L) res.a[l+i]=s.a[L+i];
        int lt=l+R-L+1;
        REP(i,0,r-l) res.a[lt+i]=s.a[l+i];
        return res;
    }
    
    int Not(Node s)
    {
        int res=0;
        REP(i,1,n-1) res+=(s.a[i]+1!=s.a[i+1]);
        return res;
    }
    
    int dfs(Node s,int cur,int maxd)
    {
        if(cur==maxd){
            if(judge(s)) return 1;
            return 0;
        }
        if(cur*3+Not(s)>maxd*3) return 0;
        int res=0;
        REP(l,1,n-1){
            REP(r,l,n-1){
                REP(R,r+1,n){
                    Node ns=cut(s,l,r,r+1,R);
                    res|=dfs(ns,cur+1,maxd);
                    if(res) return 1;
                }
            }
        }
        return res;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int casen=1;
        while(cin>>n,n){
            s.read();
            int ans=INF;
            REP(i,0,n){
                if(dfs(s,0,i)){
                    ans=i;break;
                }
            }
            printf("Case %d: %d
    ",casen++,ans);
        }
        return 0;
    }
    View Code

    K题:

    又是一道经典的状态空间搜索问题。这里如果用bfs的话要分三次,而IDA*依旧优势明显,效率高,代码短,注意每一步只能改变一个,所以估价函数为cur+不一样的个数>maxd,这里不一样的个数取最大就可以了,就不用分三次了。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    struct State
    {
        int a[24];
    };State s;
    string str;
    int ans,x;
    int A[]={0,2,6,11,15,20,22};
    int B[]={1,3,8,12,17,21,23};
    int C[]={4,5,6,7,8,9,10};
    int D[]={13,14,15,16,17,18,19};
    int Y[]={6,7,8,11,12,15,16,17};
    
    /*
        0   1
        2   3
    4 5 6 7 8 9 10
        11  12
    3 4 5 6 7 8 19
        20  21
        22  23
    */
    
    void debug(State s)
    {
        printf("      ");printf("%2d    %2d
    ",s.a[0],s.a[1]);
        printf("      ");printf("%2d    %2d
    ",s.a[2],s.a[3]);
        REP(i,4,10) printf("%2d ",s.a[i]);printf("
    ");
        printf("      ");printf("%2d    %2d
    ",s.a[11],s.a[12]);
        REP(i,13,19) printf("%2d ",s.a[i]);printf("
    ");
        printf("      ");printf("%2d    %2d
    ",s.a[20],s.a[21]);
        printf("      ");printf("%2d    %2d
    ",s.a[22],s.a[23]);
        cout<<endl;
    }
    
    State mov(State s,int *A,bool tag)
    {
        if(tag){
            int tmp=s.a[A[0]];
            REP(i,1,6) s.a[A[i-1]]=s.a[A[i]];
            s.a[A[6]]=tmp;
            return s;
        }
        else{
            int tmp=s.a[A[6]];
            for(int i=6;i>=1;i--) s.a[A[i]]=s.a[A[i-1]];
            s.a[A[0]]=tmp;
            return s;
        }
    }
    
    State go(State s,char ch)
    {
        State ns=s;
        if(ch=='A') ns=mov(s,A,1);
        if(ch=='B') ns=mov(s,B,1);
        if(ch=='C') ns=mov(s,C,0);
        if(ch=='D') ns=mov(s,D,0);
        if(ch=='E') ns=mov(s,B,0);
        if(ch=='F') ns=mov(s,A,0);
        if(ch=='G') ns=mov(s,D,1);
        if(ch=='H') ns=mov(s,C,1);
        return ns;
    }
    
    int judge(State s)
    {
        REP(i,1,7) if(s.a[Y[i]]!=s.a[Y[0]]) return 0;
        return s.a[Y[0]];
    }
    
    int Not(State s)
    {
        int cnt[4]={0};
        REP(i,0,7){
            cnt[s.a[Y[i]]]++;
        }
        return max(cnt[1],max(cnt[2],cnt[3]));
    }
    
    bool dfs(State s,int cur,int maxd,string road)
    {
    
        if(cur==maxd){
            int xx=judge(s);
            if(xx){
                str=road;
                x=xx;
                //debug(s);
                return 1;
            }
            return 0;
        }
        if(cur+8-Not(s)>maxd) return 0;
        for(char ch='A';ch<='H';ch++){
            State ns=go(s,ch);
            if(dfs(ns,cur+1,maxd,road+ch)) return 1;
        }
        return 0;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int st;
        while(cin>>st){
            if(st==0) return 0;
            s.a[0]=st;
            REP(i,1,23) scanf("%d",&s.a[i]);
            //debug(s);debug(mov(s,C,0));
            for(int i=0;;i++){
                if(dfs(s,0,i,"")){
                    ans=i;break;
                }
            }
            if(ans==0) puts("No moves needed");
            else cout<<str<<endl;
            printf("%d
    ",x);
        }
    }
    View Code

    L题:

    这应该是很经典的贪心。。。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    ll N,s1,v1,s2,v2;
    
    ll solve1(ll N,ll s1,ll v1,ll s2,ll v2)
    {
        ll res=0;
        REP(i,0,N/s1){
            ll tmp=i*v1+((N-i*s1)/s2)*v2;
            res=max(tmp,res);
        }
        return res;
    }
    
    ll solve2(ll N,ll s1,ll v1,ll s2,ll v2)
    {
        //  a*s1=b*s2->v1>v2   v1/s1>v2/s2 -> v1*s2>v2*s1
        if(v1*s2<v2*s1){
            swap(s1,s2);swap(v1,v2);
        }
        ll d=__gcd(s1,s2);
        ll a=s2/d,b=s1/d;
        ll res=0;
        REP(i,0,b-1){
            ll tmp=i*v2+((N-i*s2)/s1)*v1;
            res=max(res,tmp);
        }
        return res;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;cin>>T;
        int casen=1;
        while(T--){
            scanf("%lld%lld%lld%lld%lld",&N,&s1,&v1,&s2,&v2);
            ll ans=0;
            if(N/s1<maxn) ans=solve1(N,s1,v1,s2,v2);
            else if(N/s2<maxn) ans=solve1(N,s2,v2,s1,v1);
            else ans=solve2(N,s1,v1,s2,v2);
            printf("Case #%d: %lld
    ",casen++,ans);
        }
        return 0;
    }
    View Code

    O题:

    这题大数据没过却莫名其妙地AC了。。。用的是IDA*,看来如果拼人品的话就IDA*吧。。。由于这题的另一种解法是dancing links,有时间学dancing links的时候一定回来看这题。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int n,k;
    struct State
    {
        bool has[61];
        int cnt;
        int c[61];
        int sum_c,max_c;
        int Cnt()
        {
            int res=0;
            REP(d,1,n){
                REP(r,0,n-d){
                    REP(c,1,n-d+1){
                        int x=1;
                        int st=r*(2*n+1)+c;
                        REP(j,0,d-1) x&=(has[st+j]&has[st+n+j*(2*n+1)]&has[st+n+d+j*(2*n+1)]&has[st+d*(2*n+1)+j]);
                        res+=x;
                    }
                }
            }
            return res;
        }
        void cal_c()
        {
            MS0(c);max_c=0;sum_c=0;
            REP(i,1,2*n*(n+1)){
                if(has[i]){
                    has[i]=0;
                    int tmp=cnt;
                    cnt=Cnt();
                    c[i]=tmp-cnt;
                    max_c=max(c[i],max_c);
                    sum_c+=c[i];
                    has[i]=1;
                    cnt=tmp;
                }
            }
        }
    };State s;
    
    bool dfs(State s,int cur,int maxd)
    {
        s.cal_c();
        if(cur==maxd) return s.cnt==0;
        if(cur+s.cnt-s.sum_c>maxd) return 0;
        REP(i,1,2*n*(n+1)){
            if(s.has[i]){
                if(s.c[i]==s.max_c){
                    State ns=s;
                    ns.has[i]=0;
                    ns.cnt=s.cnt-s.c[i];
                    if(dfs(ns,cur+1,maxd)) return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%d%d",&n,&k);
            REP(i,1,2*n*(n+1)) s.has[i]=1;
            REP(i,1,k){
                int x;scanf("%d",&x);
                s.has[x]=0;
            }
            s.cnt=s.Cnt();
            s.cal_c();
            int ans=INF;
            REP(i,1,60){
                if(dfs(s,0,i)){
                    ans=i;break;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    linux进程调度策略(SCHED_OTHER,SCHED_FIFO,SCHED_RR)
    10、单机运行环境搭建之 --Windows下mysqldump 备份与还原数据库
    5、单机运行环境搭建之 --CentOS6.4拷贝Tomcat7形成集群
    9、单机运行环境搭建之 --CentOS6.4下mysqldump 备份与还原数据库
    7、单机运行环境搭建之 --CentOS6.4安装Memcached
    13、单机运行环境搭建之 --Centos6.4下iptables保护主机安全
    12、单机运行环境搭建之 --Centos6.4下webbench压力测试
    6、单机运行环境搭建之 --CentOS6.4安装MySQL 5.6.10并修改MySQL的root用户密码
    4、单机运行环境搭建之 --CentOS6.5优化Tomcat7
    8、单机运行环境搭建之 --CentOS6.4安装vsftpd
  • 原文地址:https://www.cnblogs.com/--560/p/4987887.html
Copyright © 2020-2023  润新知