智慧搜索

剪枝

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

/*

*/
#define method_1
#ifdef method_1
/*
蓝书上的例题,不再赘述。 
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<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<

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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<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_queueq;
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(;acnt){
                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(aINF||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<

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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<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];
queueq;
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
#include
#include
#include
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 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
好复杂,不想写。
代码如下


你可能感兴趣的:(智慧搜索)