智慧搜索

剪枝

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
好复杂,不想写。
代码如下


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,706评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,002评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,462评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,375评论 0 216
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,763评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,849评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,033评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,768评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,490评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,734评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,204评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,566评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,227评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,137评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,934评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,926评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,774评论 2 274

推荐阅读更多精彩内容

  • 博弈DP POJ 1082: Calendar Game从最终状态向前dp即可。注意如下两点:1 需要保证前后的状...
    云中翻月阅读 273评论 0 3
  • 最大化最小值 POJ 3258: River Hopscotch同noip跳石头。代码如下 POJ 3273: M...
    云中翻月阅读 519评论 0 3
  • DFS POJ 1979: Red and Black简单的DFS找四联通块即可。代码如下 POJ 3009: C...
    云中翻月阅读 133评论 0 2
  • 基础DP POJ 3176: Cow Bowling数字三角形问题,DP方程不再赘述。代码如下 POJ 2229:...
    云中翻月阅读 555评论 0 1
  • 尺取法 POJ 2566: Bound Found题解链接 https://www.cnblogs.com/smi...
    云中翻月阅读 363评论 0 2