美文网首页
智慧搜索

智慧搜索

作者: 云中翻月 | 来源:发表于2019-10-15 10:57 被阅读0次

    剪枝

    POJ 1011: Sticks
    蓝书上的例题,不再赘述。
    代码如下

    /*
    
    */
    #define method_1
    #ifdef method_1
    /*
    蓝书上的例题,不再赘述。 
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iomanip>
    #include<ctime>
    #include<string>
    #define D(x) cout<<#x<<" = "<<x<<"  "
    #define E cout<<endl
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>pii;
    const int maxn=64+5;
    const int maxl=50+5;
    const int INF=0x3f3f3f3f;
    int n,a[maxn];
    int v[maxn],sum,cnt,minl;
    void init(){
        sum=0,minl=INF;
        memset(v,0,sizeof(v));
    }
    bool dfs(int stick,int cab,int last,int len){ 
    //拼接到第stick根 当前长度cab 上一根为第last根木棒 原先一根木棒长度len 
        if(stick>cnt) return true;
        if(cab==len) return dfs(stick+1,0,1,len);
        int fail=0;
        for(int i=last;i<=n;i++){ //从last开始尝试 
            if(v[i]) continue;
            if(a[i]==fail) continue; //同样长度的木棒 每根只尝试一次 
            if(cab+a[i]>len) continue;
            v[i]=1;
            if(dfs(stick,cab+a[i],i,len)) return true;
            v[i]=0;
            fail=a[i]; 
            //用当前根放进去会最终失败 
            if(cab+a[i]==len) return false; //如果加入当前根能拼好这条木棒 但后面的拼不好 就算失败 
            if(cab==0) return false; //放入当前根之前还是空的 也算失败 
        }
        return false;
    }
    int main() {
        ios::sync_with_stdio(false);
        //freopen("Sticks.in","r",stdin);
        while(cin>>n){
            if(!n) break;
            init();
            for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i],minl=min(minl,a[i]);  
            sort(a+1,a+n+1);
            reverse(a+1,a+n+1);
            for(int i=minl;i<=sum;i++){
                if(sum%i) continue;
                cnt=sum/i;
                if(dfs(1,0,1,i)){
                    cout<<i<<endl;
                    break;
                }
            }
        }
        return 0;
    }
    #endif
    #ifdef method_2
    /*
    
    */
    
    #endif
    #ifdef method_3
    /*
    
    */
    
    #endif
    

    POJ 2046: Gap
    规则好复杂,看不懂。
    代码如下

    
    

    POJ 3134: Power Calculus
    题解链接 https://www.jianshu.com/p/283c8557487b
    代码如下

    /*
    
    */
    #define method_1
    #ifdef method_1
    /*
    题解链接 https://www.jianshu.com/p/283c8557487b 
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iomanip>
    #include<ctime>
    #define D(x) cout<<#x<<" = "<<x<<"  "
    #define E cout<<endl
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>pii;
    const int maxn=1000000+5;
    const int INF=32768;
    const int mod=999983;
    int n,d[maxn],tot,head[maxn];
    struct node{
        int a,b,val,cnt;
    };
    bool operator<(const node &x,const node &y){
        return x.val+x.cnt>y.val+y.cnt;
    }
    struct node1{
        int from;
        pii to;
    }edge[maxn];
    priority_queue<node>q;
    void init(){
        memset(head,0,sizeof(head));
        tot=1;
        while(q.size()) q.pop();
    } 
    int gcd(int a,int b){
        return !b?a:gcd(b,a%b);
    }
    int cal(int a){
        int val=0;
        for(;a<n;a<<=1)val++;
        return val;
    }
    bool update(int a,int b,int cnt){
        int ha=a*b%mod;
        for(int i=head[ha];i;i=edge[i].from){
            if(edge[i].to.first==a&&edge[i].to.second==b){
                if(d[i]>cnt){
                    d[i]=cnt;
                    return true;
                }
                return false;
            }
        }
        d[++tot]=cnt;
        edge[tot].to.first=a,edge[tot].to.second=b;
        edge[tot].from=head[ha],head[ha]=tot;
        return true;
    }
    void insert(int a,int b,int cnt){
        if(a<b) swap(a,b);
        if(a>INF||b>INF) return;
        if(n%gcd(a,b)) return;
        bool f=update(a,b,cnt);
        if(f){
            node nd;
            nd.a=a,nd.b=b,nd.val=cal(a),nd.cnt=cnt;
            q.push(nd);
        }
    }
    int astar(){
        insert(1,0,0);
        while(q.size()){
            node now=q.top();q.pop();
            if(now.a==n||now.b==n) return now.cnt;
            insert(now.a*2,now.b,now.cnt+1);
            insert(now.a,now.b*2,now.cnt+1);
            if(now.a) insert(now.a*2,now.a,now.cnt+1);
            if(now.b) insert(now.b*2,now.b,now.cnt+1);
            if(now.a-now.b>=0){
                insert(now.a-now.b,now.a,now.cnt+1),insert(now.a-now.b,now.b,now.cnt+1);
            }
            if(now.b-now.a>=0){
                insert(now.b-now.a,now.a,now.cnt+1),insert(now.b-now.a,now.b,now.cnt+1);
            }
            insert(now.a+now.b,now.a,now.cnt+1),insert(now.a+now.b,now.b,now.cnt+1);
        }
    }
    int main() {
        ios::sync_with_stdio(false);
        //freopen("Power Calculus.in","r",stdin);
        while(cin>>n){
            if(n==0) break;
            init();
            cout<<astar()<<endl;
        }
        return 0;
    }
    #endif
    #ifdef method_2
    /*
    
    */
    
    #endif
    #ifdef method_3
    /*
    
    */
    
    #endif
    

    A_star与IDA_star

    POJ 3523: The Morning after Halloween
    照着刘汝佳的代码抄的,竟然比刘汝佳的快1000ms。
    method_1为自己实现的版本,method_2为刘汝佳的代码。
    代码如下

    /*
    
    */
    #define method_1
    #ifdef method_1
    /*
    照着刘汝佳的代码抄的,竟然比刘汝佳的快1000ms。
    method_1为自己实现的版本,method_2为刘汝佳的代码。 
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iomanip>
    #include<ctime>
    #include<string>
    #define D(x) cout<<#x<<" = "<<x<<"  "
    #define E cout<<endl
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>pii;
    const int maxw=20+5;
    const int maxn=150+5;
    const int maxg=3+5;
    const int maxd=5+5;
    const int INF=0x3f3f3f3f;
    const int dx[]= {0,0,-1,1,0};
    const int dy[]= {1,-1,0,0,0};
    int h,w,n;
    char a[maxw][maxw];
    int d[maxn][maxn][maxn];
    int deg[maxn],G[maxn][maxd];
    int tot,x[maxn],y[maxn],id[maxw][maxw],s[maxg],t[maxg];
    queue<int>q;
    void init() {
        tot=0;
        memset(d,-1,sizeof(d));
        memset(deg,0,sizeof(deg));
        while(q.size()) q.pop();
    }
    inline int ID(int a,int b,int c) {
        return (a<<16)|(b<<8)|c;
    }
    inline bool conflict(int a,int b,int a2,int b2){
        return (a2==b2)||(a==b2&&b==a2);
    }
    void pre() {
        for(int i=1;i<=tot;i++){
            for(int j=0;j<=4;j++){
                int nx=x[i]+dx[j],ny=y[i]+dy[j];
                // "Outermost cells of a map are walls" means we don't need to check out-of-bound
                if(a[nx][ny]=='#') continue;
                G[i][++deg[i]]=id[nx][ny];
            }
        }
        if(n<=2){
            deg[++tot]=1,s['c'-'a']=t['c'-'a']=tot,G[tot][1]=tot;
        }
        if(n<=1){
            deg[++tot]=1,s['b'-'a']=t['b'-'a']=tot,G[tot][1]=tot;
        }
    }
    int bfs() {
        q.push(ID(s[0],s[1],s[2]));
        d[s[0]][s[1]][s[2]]=0;
        while(q.size()){
            int now=q.front();q.pop();
            int a=now>>16,b=(now>>8)&0xff,c=now&0xff;
            if(a==t[0]&&b==t[1]&&c==t[2]) return d[a][b][c];
            for(int i=1;i<=deg[a];i++){
                int a2=G[a][i];
                for(int j=1;j<=deg[b];j++){
                    int b2=G[b][j];
                    if(conflict(a,b,a2,b2)) continue;
                    for(int k=1;k<=deg[c];k++){
                        int c2=G[c][k];
                        if(conflict(a,c,a2,c2)||conflict(b,c,b2,c2)) continue;
                        if(d[a2][b2][c2]!=-1) continue;
                        d[a2][b2][c2]=d[a][b][c]+1;
                        q.push(ID(a2,b2,c2));
                    }
                }
            }
        }
        return -1;
    }
    int main() {
    //  ios::sync_with_stdio(false);
        //freopen("The Morning after Halloween.in","r",stdin);
        while(scanf("%d%d%d",&w,&h,&n)) {
            if(!w&&!h&&!n) break;
            init();
            getchar();
            for(int i=1; i<=h; i++) {
                for(int j=1; j<=w; j++) {
                    scanf("%c",&a[i][j]);
                    if(a[i][j]=='#') continue;
                    x[++tot]=i,y[tot]=j,id[i][j]=tot;
                    if(islower(a[i][j])) s[a[i][j]-'a']=tot;
                    if(isupper(a[i][j])) t[a[i][j]-'A']=tot;
                }
                getchar();
            }
            /*
            for(int i=1;i<=h;i++){
                for(int j=1;j<=w;j++) printf("%c",a[i][j]);
                printf("\n");
            }
            */
            pre();
            printf("%d\n",bfs());
        }
        return 0;
    }
    #endif
    #ifdef method_2
    /*
    
    */
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<queue>
    using namespace std;
    
    const int maxs = 20;
    const int maxn = 150; /// 75% cells plus 2 fake nodes
    const int dx[]= {1,-1,0,0,0}; /// 4 moves, plus "no move"
    const int dy[]= {0,0,1,-1,0};
    
    inline int ID(int a, int b, int c) {
        return (a<<16)|(b<<8)|c;///由于int 类型保存8个字节,所以这个操作将a放到了最前面的8个字节,b放到了中间的8个字节,c放到了最后的8个字节
    }
    
    int s[3], t[3]; /// starting/ending position of each ghost
    
    int deg[maxn], G[maxn][5]; /// target cells for each move (including "no move").deg 表示出度,存储能够前进的方向
    
    inline bool conflict(int a, int b, int a2, int b2) {
        return a2 == b2 || (a2 == b && b2 == a);///第一个表示a,b进入同一空格,第二个表示2者交换位置
    }
    
    int d[maxn][maxn][maxn]; /// distance from starting state
    
    int bfs() {
        queue<int> q;
        memset(d, -1, sizeof(d));
        q.push(ID(s[0], s[1], s[2])); /// starting node
        d[s[0]][s[1]][s[2]] = 0;
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            int a = u>>16, b = (u>>8)&0xff, c = u&0xff;///&0xff表示取最后的8个字节
            if(a == t[0] && b == t[1] && c == t[2]) return d[a][b][c]; /// solution found
            for(int i = 0; i < deg[a]; i++) {
                int a2 = G[a][i];
                for(int j = 0; j < deg[b]; j++) {
                    int b2 = G[b][j];
                    if(conflict(a, b, a2, b2)) continue;
                    for(int k = 0; k < deg[c]; k++) {
                        int c2 = G[c][k];
                        if(conflict(a, c, a2, c2)) continue;
                        if(conflict(b, c, b2, c2)) continue;
                        if(d[a2][b2][c2] != -1) continue;///判断是否被访问过
                        d[a2][b2][c2] = d[a][b][c]+1;
                        q.push(ID(a2, b2, c2));
                    }
                }
            }
        }
        return -1;
    }
    
    int main() {
        //freopen("The Morning after Halloween.in","r",stdin);
        int w, h, n;
    
        while(scanf("%d%d%d\n", &w, &h, &n) == 3 && n) {
            char maze[20][20];
            for(int i = 0; i < h; i++)
                fgets(maze[i], 20, stdin);
    
            /// extract empty cells
            int cnt, x[maxn], y[maxn], id[maxs][maxs]; ///cnt is the number of empty cells
    //      memset(id,-1,sizeof(id));
            cnt = 0;
            for(int i = 0; i < h; i++)
                for(int j = 0; j < w; j++)
                    if(maze[i][j] != '#') {
                        x[cnt] = i;
                        y[cnt] = j;
                        id[i][j] = cnt;
                        if(islower(maze[i][j])) s[maze[i][j] - 'a'] = cnt;
                        else if(isupper(maze[i][j])) t[maze[i][j] - 'A'] = cnt;
                        cnt++;
                    }
    //      for(int i=0;i<=h-1;i++){
    //          for(int j=0;j<=w-1;j++) printf("%2d",id[i][j]);
    //          printf("\n");
    //      }
            /// build a graph of empty cells
            for(int i = 0; i < cnt; i++) {
                deg[i] = 0;
                for(int dir = 0; dir < 5; dir++) {
                    int nx = x[i]+dx[dir], ny = y[i]+dy[dir];
                    /// "Outermost cells of a map are walls" means we don't need to check out-of-bound
                    if(maze[nx][ny] != '#') G[i][deg[i]++] = id[nx][ny];///出度+1,指向空格区域
                }
            }
    
            /// add fakes nodes so that in each case we have 3 ghosts. this makes the code shorter
            if(n <= 2) {
                deg[cnt] = 1;
                G[cnt][0] = cnt;
                s[2] = t[2] = cnt++;
            }
            if(n <= 1) {
                deg[cnt] = 1;
                G[cnt][0] = cnt;
                s[1] = t[1] = cnt++;
            }
    
            printf("%d\n", bfs());
        }
        return 0;
    }
    #endif
    #ifdef method_3
    /*
    
    */
    
    #endif
    

    POJ 2032: Square Carpets
    题解链接 http://www.hankcs.com/program/algorithm/poj-2032-square-carpets.html
    好复杂,不想写。
    代码如下

    
    

    相关文章

      网友评论

          本文标题:智慧搜索

          本文链接:https://www.haomeiwen.com/subject/oufqpctx.html