ida* 的一些题 ida*小结

本文深入探讨了IDA*和A*算法在解决搜索问题中的应用,包括八数码拼图、旋转游戏等典型问题。对比了两种算法的优缺点,如IDA*的简单状态存储与A*的复杂判重机制,以及IDA*对深度控制的优势。通过实例代码展示了估价函数设计的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         这些题都是http://www.cnblogs.com/ambition/archive/2011/07/25/search_plus.html  里的。。我的一些代码也参考了里边的代码

HDU 1043 Eight      话说是一道涉及到人生完整不完整的题 八数码

      判断有没有解:求出所给状态的逆序数m,如果同是奇数则无解,偶数则有解。  why?  因为移动一次逆序数 加2 或 减2 (我也不会证,就是自己试了下,发现是)

   在我的程序中空位用0表示

   方法一: A*

   估价函数: 计算当前状态到目标状态的 曼哈顿距离。 因为移动一次,曼哈顿距离 加1或减1,所以直接返回曼哈顿距离

   状态存储: 采用 康托 法。 把一个图转化成一个数。

      判重:   把图转化为 康托数后,用个 hash       9!=362880

   然后就是bfs了。

   用一个pre 数组记录路径

        A* 是要用优先队列了,无奈于对堆不太熟练,于是用了STL

下面对程序的执行过程简略介绍:

   对于每个结点存 了当前的图G(用了康托后就是一个数, (可以不用康托数,直接开个数组 记录整个图)我的第二个程序就是这样的。

                                  当前已走多少步step,

                                 当前状态到目标状态的曼哈顿距离dis,

                                则预计至少h步到目标状态(h=step+dis)

 优先队列就是根据 按上从小到大排序的      (STL 中默认是从大到小,所以要自己写个比较函数,或者重载运算符(我是重载运算符的)

        1.读入数据:

         如果是x换成0

   2.判断逆序数是否为奇数

            奇数:无解

            偶数:继续

   3.bfs

                1.起点入队

      2.向四个方向 搜索,计算 step,dis,h

                3.判重

          不重,入队,设置其前趋

      4.遇到终点 则结束。

    输出结果,是倒着的,放在数组里。

A*代码:

View Code
  1 #include<iostream>
  2 #include<queue>
  3 using namespace std;
  4 int vis[362885];
  5 int factor[]={1,1,2,6,24,120,720,5040,40320,362880,3628800}; //用于康托
  6 int mx[]={1,0,0,-1};   //四个移动方向的控制
  7 int my[]={0,-1,1,0};
  8 char x[11],ans[362885];//由于BFS搜得的结果在是倒着的。所以先把移动序列正着存放在ans中
  9 char cov[]={'d','l','r','u'};   
 10 int na;
 11 const int N=9;
 12 struct node
 13 {
 14     int step;//到G这个状态已经走了step步
 15     int dis;//用估价函数所得
 16     int h;  //h=step+dis 用于优先队列的优先级
 17     int G;  //当前状态,是一个数,用反康托算法展开就可以得到这个状态
 18 };
 19 struct s
 20 {
 21     int sum;  
 22     int d;   //移动方向
 23 }pre[362885];//用于记录当前状态的的前驱
 24 priority_queue<node> Q;
 25 int Start,End;
 26 bool operator<(const node &t1,const node &t2)
 27 {
 28     if(t1.h==t2.h)
 29         return t1.step<t2.step;
 30     else
 31         return t1.h>t2.h;
 32 }
 33 int cantor(char *y,int n)    //康托 把这个序列变成一个数
 34 {
 35     int sum=0,i,j,cnt;
 36     for(i=0;i<n;i++)
 37     {
 38         cnt=0;
 39         for(j=i+1;j<n;j++)
 40             if(y[j]<y[i])
 41                 cnt++;
 42         sum+=factor[n-i-1]*cnt;
 43     }
 44     return sum;
 45 }           
 46 void fcantor(char *y,int n,int m)  //反康托,把一个数n变成一个排列
 47 {
 48     int i,j,cnt,k;
 49     bool vis[15]={0};
 50     for(i=0;i<m;i++)
 51     {
 52         k=n/factor[m-i-1];
 53         n%=factor[m-i-1];
 54         cnt=0;
 55         for(j=1;j<=m;j++)
 56         {
 57             if(!vis[j])
 58                 cnt++;
 59             if(cnt==k+1)
 60                 break;
 61         }
 62         y[i]=j;
 63         vis[j]=true;
 64     }
 65 }       
 66 int inverse_number(char *y,int m)   //求逆序数 
 67 {
 68     int i,j,cnt=0;
 69     for(i=1;i<m;i++)
 70     {
 71         if(y[i]==N)continue;
 72         for(j=i-1;j>=0;j--)
 73             if(y[j]>y[i]&&y[j]!=N)
 74                 cnt++;
 75     }
 76     return !(cnt&1);
 77 }
 78 int man_dis(char *y,int n)  // 曼哈顿距离
 79 {
 80     int i,j,tx,ty,dis=0;
 81     for(i=0;i<3;i++)
 82         for(j=0;j<3;j++)
 83         {
 84             if(y[i*3+j]==9)continue;
 85             tx=(y[i*3+j]-1)/3;
 86             ty=(y[i*3+j]-1)%3;
 87             dis+=abs(tx-i)+abs(ty-j);
 88         }
 89         return dis;
 90 }
 91 void bfs()
 92 {
 93     while(!Q.empty())Q.pop();
 94     memset(vis,0,sizeof(vis));
 95     node t,p;
 96     t.step=0; t.G=Start; t.dis=0;
 97     Q.push(t); 
 98     vis[Start]=true;
 99     pre[Start].d=-1;pre[Start].sum=-1;
100     char y[11];
101     int fx,fy,tx,ty,i;
102     while(!Q.empty())
103     {
104         t=Q.top();
105         Q.pop();
106         fcantor(y,t.G,N);
107         for(i=0;i<N;i++)
108             if(y[i]==9)
109                 break;
110         fx=i/3; fy=i%3;
111         for(i=0;i<4;i++)      //四个方向 广搜
112         {
113             p=t;
114             tx=fx+mx[i];
115             ty=fy+my[i];
116             if(tx<0||ty<0||tx>=3||ty>=3)
117                 continue;
118             swap(y[fx*3+fy],y[tx*3+ty]);     //移动
119             p.G=cantor(y,N);                //转化为一个数
120             p.dis=man_dis(y,N);              //估价函数
121             p.step++;
122             p.h=p.step+p.dis;
123             if(!vis[p.G])                  //判重
124             {
125                 vis[p.G]=true;
126                 Q.push(p);
127                 pre[p.G].sum=t.G;
128                 pre[p.G].d=i;
129             }
130             if(p.G==0)
131                 return;
132             swap(y[fx*3+fy],y[tx*3+ty]);          //不要忘了换回来
133         }
134     }
135 }
136 int main()
137 {
138     //freopen("input.txt","r",stdin);
139     int i;
140     while(true)
141     {
142         for(i=0;i<N;i++)
143         {
144             if(!(cin>>x[i]))
145                 return 0;
146             if(x[i]=='x')
147                 x[i]=N;
148             else
149                 x[i]-='0';
150 
151         }
152         Start=cantor(x,N);
153         End=0;
154         if(inverse_number(x,N))
155         {
156             bfs();
157             na=0;
158             while(pre[End].sum!=-1)
159             {
160                 ans[na++]=cov[pre[End].d];
161                 End=pre[End].sum;
162             }
163             for(i=na-1;i>=0;i--)
164                 cout<<ans[i];
165         }
166         else 
167             cout<<"unsolvable";
168         cout<<endl;
169     }
170     return 0;
171 }

存图时不用康托数,直接保存整个图的代码。这样的发处是,每次出队后,不用把数把解为图了

View Code
  1 #include<iostream>
  2 #include<queue>
  3 using namespace std;
  4 int vis[362885];
  5 int factor[]={1,1,2,6,24,120,720,5040,40320,362880,3628800};
  6 int mx[]={1,0,0,-1};
  7 int my[]={0,-1,1,0};
  8 char x[11],ans[362885];
  9 char cov[]={'d','l','r','u'};
 10 int na;
 11 const int N=9;
 12 struct node
 13 {
 14     int step;
 15     int dis;
 16     int h;
 17     char G[11];
 18 };
 19 struct s
 20 {
 21     int sum;
 22     int d;
 23 }pre[362885];
 24 priority_queue<node> Q;
 25 int Start,End;
 26 bool operator<(const node &t1,const node &t2)
 27 {
 28     if(t1.h==t2.h)
 29         return t1.step<t2.step;
 30     else
 31         return t1.h>t2.h;
 32 }
 33 int cantor(char *y,int n)
 34 {
 35     int sum=0,i,j,cnt;
 36     for(i=0;i<n;i++)
 37     {
 38         cnt=0;
 39         for(j=i+1;j<n;j++)
 40             if(y[j]<y[i])
 41                 cnt++;
 42         sum+=factor[n-i-1]*cnt;
 43     }
 44     return sum;
 45 }
 46 void fcantor(char *y,int n,int m)
 47 {
 48     int i,j,cnt,k;
 49     bool vis[15]={0};
 50     for(i=0;i<m;i++)
 51     {
 52         k=n/factor[m-i-1];
 53         n%=factor[m-i-1];
 54         cnt=0;
 55         for(j=1;j<=m;j++)
 56         {
 57             if(!vis[j])
 58                 cnt++;
 59             if(cnt==k+1)
 60                 break;
 61         }
 62         y[i]=j;
 63         vis[j]=true;
 64     }
 65 }
 66 int inverse_number(char *y,int m)
 67 {
 68     int i,j,cnt=0;
 69     for(i=1;i<m;i++)
 70     {
 71         if(y[i]==N)continue;
 72         for(j=i-1;j>=0;j--)
 73             if(y[j]>y[i]&&y[j]!=N)
 74                 cnt++;
 75     }
 76     return !(cnt&1);
 77 }
 78 int man_dis(char *y,int n)
 79 {
 80     int i,j,tx,ty,dis=0;
 81     for(i=0;i<3;i++)
 82         for(j=0;j<3;j++)
 83         {
 84             if(y[i*3+j]==9)continue;
 85             tx=(y[i*3+j]-1)/3;
 86             ty=(y[i*3+j]-1)%3;
 87             dis+=abs(tx-i)+abs(ty-j);
 88         }
 89         return dis;
 90 }
 91 void bfs()
 92 {
 93     while(!Q.empty())Q.pop();
 94     memset(vis,0,sizeof(vis));
 95     node t,p;
 96     t.step=0;  t.dis=0;
 97     memcpy(t.G,x,sizeof(x));
 98     Q.push(t); 
 99     vis[Start]=true;
100     pre[Start].d=-1;pre[Start].sum=-1;
101     char y[11];
102     int fx,fy,tx,ty,i,fn,tn;
103     while(!Q.empty())
104     {
105         t=Q.top();
106         Q.pop();
107         fn=cantor(t.G,N);
108         //cout<<t.dis<<" "<<t.step<<" "<<t.h<<endl;
109         for(i=0;i<N;i++)
110             if(t.G[i]==9)
111                 break;
112         fx=i/3; fy=i%3;
113         for(i=0;i<4;i++)
114         {
115             p=t;
116             tx=fx+mx[i];
117             ty=fy+my[i];
118             if(tx<0||ty<0||tx>=3||ty>=3)
119                 continue;
120             p.G[fx*3+fy]=p.G[tx*3+ty];
121             p.G[tx*3+ty]=9;
122             tn=cantor(p.G,N);
123             p.dis=man_dis(p.G,N);
124             p.step++;
125             p.h=p.step+p.dis;
126             if(!vis[tn])
127             {
128                 vis[tn]=true;
129                 Q.push(p);
130                 pre[tn].sum=fn;
131                 pre[tn].d=i;
132             }
133             if(tn==0)
134                 return;
135         }
136     }
137 }
138 int main()
139 {
140     //freopen("input.txt","r",stdin);
141     int i;
142     while(true)
143     {
144         for(i=0;i<N;i++)
145         {
146             if(!(cin>>x[i]))
147                 return 0;
148             if(x[i]=='x')
149                 x[i]=N;
150             else
151                 x[i]-='0';
152 
153         }
154         /*cout<<cantor(x,N)<<endl;
155         int t;
156         cout<<"input t to x\n";
157         cin>>t;
158         fcantor(x,t,N);
159         for(i=0;i<N;i++)
160             cout<<(int)x[i];
161         cout<<endl;*/

162         //cout<<inverse_number(x,N)<<endl;
163         Start=cantor(x,N);
164         End=0;
165         if(inverse_number(x,N))
166         {
167             bfs();
168             na=0;
169             while(pre[End].sum!=-1)
170             {
171                  ans[na++]=cov[pre[End].d];
172                  End=pre[End].sum;
173              }
174             for(i=na-1;i>=0;i--)
175                 cout<<ans[i];
176         }
177         else 
178             cout<<"unsolvable";
179         cout<<endl;
180     }
181     return 0;
182 }

 

 

方法二:

      先从终点向起点搜出所有状态,问哪个就输出哪个。

View Code
  1 //八数码
  2 #include<iostream>
  3 #include<queue>
  4 using namespace std;
  5 char x[11];
  6 int factor[]={1,1,2,6,24,120,720,5040,40320,362880,3628800};
  7 bool vis[362881];
  8 int ans;
  9 #define N 9
 10 int mx[]={0,0,1,-1};  
 11 int my[]={1,-1,0,0};
 12 struct
 13 {
 14     int d;
 15     int sum;
 16 }pre[362881];
 17 char cov[]={'l','r','u','d'}; //这四个方向都设反了。因为是倒搜
 18 int cantor(char *y,int n)    /*将全排列转换为一个数*/
 19 {
 20     int i,j,cnt,sum=0;
 21     for(i=0;i<n;i++)
 22     {
 23         cnt=0;
 24         for(j=i+1;j<n;j++)
 25             if(y[j]<y[i])
 26                 cnt++;
 27         sum+=factor[n-i-1]*cnt;
 28     }
 29     return sum;
 30 }
 31 struct node
 32 {
 33     char G[3][3];
 34     int x,y,ct;
 35 }Start;
 36 queue<node> Q;
 37 int inverse_number(char *y,int m)
 38 {
 39     int i,j,cnt=0;
 40     for(i=1;i<m;i++)
 41     {
 42         if(y[i]==N)continue;
 43         for(j=i-1;j>=0;j--)
 44             if(y[j]>y[i]&&y[j]!=N)
 45                 cnt++;
 46     }
 47     return !(cnt&1);
 48 }
 49 void bfs()
 50 {
 51     memset(vis,0,sizeof(vis));
 52     memset(pre,-1,sizeof(pre));
 53     int i,j,tn,tx,ty;
 54     node t;
 55     for(i=0;i<3;i++)
 56         for(j=0;j<3;j++)
 57             t.G[i][j]=i*3+j+1;
 58     t.x=2,t.y=2;t.ct=0;
 59     while(!Q.empty())Q.pop();
 60     Q.push(t);
 61     vis[0]=true;
 62     while(!Q.empty())
 63     {
 64         t=Q.front();Q.pop();
 65         node p;
 66         for(i=0;i<4;i++)
 67         {
 68             tx=t.x+mx[i];
 69             ty=t.y+my[i];
 70             if(tx<0||ty<0||tx>=3||ty>=3)
 71                 continue;
 72             p=t;
 73             p.G[p.x][p.y]=p.G[tx][ty];
 74             p.G[tx][ty]=9;
 75             p.x=tx;p.y=ty;
 76             tn=cantor(p.G[0],9);
 77             p.ct=tn;
 78             if(vis[tn])continue;
 79             vis[tn]=true;
 80 
 81             Q.push(p);
 82             pre[tn].d=i;
 83             pre[tn].sum=t.ct;
 84         }
 85     }
 86 }
 87 int main()
 88 {
 89     //freopen("input.txt","r",stdin);
 90     int i,j;
 91     bfs();
 92     while(true)
 93     {
 94         for(i=0;i<3;i++)
 95             for(j=0;j<3;j++)
 96             {
 97                 if(!(cin>>Start.G[i][j]))
 98                     return 0;
 99 
100                 if(Start.G[i][j]=='x')
101                 {
102                     Start.x=i;
103                     Start.y=j;
104                     Start.G[i][j]=9;
105                 }
106                 else
107                     Start.G[i][j]-='0';
108 
109             }
110 
111 
112             if(!inverse_number(Start.G[0],9))
113             {
114                 cout<<"unsolvable"<<endl;
115                 continue;
116             }
117             ans=cantor(Start.G[0],N);
118             while(ans!=0)
119             {
120                 cout<<cov[pre[ans].d];
121                 ans=pre[ans].sum;
122             }
123             cout<<endl;
124     }
125     return 0;
126 }

 

 

HDU 1667 The Rotation Game

   这个用 ida*

         1.估价函数 

         要保证中间四个数一样,所以统计一下中间 至少 还需移动几次就能让数字相同。因为第移动一次只会 增加或减少一个数。

   2.存储状态,基本不用,只要一个数组就行了。dfs返回时把状态改回来。

   3.判 重也不用啦。  原因是,如果重复的起很多步肯定比没重复走的用的步数少。

   4.用一个数组记录路径

   5.预先写好移动的函数。

解决在dfs中 8方向函数调用问题

      当然,一个一个写也可以

看看这个吧:void (*pm[4])(int s[N][N],int x);//方便函数批量调用

 

   

代码在此:

View Code
  1 #include<iostream>
  2 using namespace std;
  3 int G[7][7];
  4 #define N 7
  5 int deep;
  6 void (*pm[4])(int s[N][N],int x);//方便函数批量调用
  7 int mx[]={2,4};
  8 int ans[100000],bs[10000],cs;
  9 char opt[4][2]={'A','B','C','D','F','E','H','G'};
 10 
 11 //**************移动******************************
 12 void up(int s[N][N],int y)
 13 {
 14     int t=s[0][y];
 15     for(int i=0;i<6;i++)
 16         s[i][y]=s[i+1][y];
 17     s[6][y]=t;
 18 }
 19 void down(int s[N][N],int y)
 20 {
 21     int t=s[6][y];
 22     for(int i=6;i>0;i--)
 23         s[i][y]=s[i-1][y];
 24     s[0][y]=t;
 25 }
 26 void left(int s[N][N],int x)
 27 {
 28     int t=s[x][0];
 29     for(int j=0;j<6;j++)
 30         s[x][j]=s[x][j+1];
 31     s[x][6]=t;
 32 }
 33 void right(int s[N][N],int x)
 34 {
 35     int t=s[x][6];
 36     for(int j=6;j>0;j--)
 37         s[x][j]=s[x][j-1];
 38     s[x][0]=t;
 39 }
 40 //******************移动结束***********************************
 41 
 42 
 43 
 44 //**************估价函数**************************************
 45 int check(int s[N][N])
 46 {
 47     s[3][3]=0;                       //把这个设为0,下边就可以用循环统计每个数字出现的个数了
 48     int i,j,cnt[4]={0};
 49     for(i=2;i<=4;i++)
 50         for(j=2;j<=4;j++)
 51             cnt[s[i][j]]++;
 52     return max(max(cnt[1],cnt[2]),cnt[3]);  //返加了其中出现的最多次
 53 }
 54 //**************估价函数结束**************************************
 55 
 56 
 57 //***********dfs*****************************
 58 bool dfs(int step)
 59 {
 60     int h=8-check(G),tj;
 61     if(h==0){cs=step;return true;}
 62     if(step+h>deep)return false;
 63     for(int i=0;i<4;i++)
 64         for(int j=0;j<2;j++)
 65         {
 66             tj=j;
 67             if(i>=2)tj=2-j-1;
 68             pm[i](G,mx[tj]);
 69             ans[step]=i;
 70             bs[step]=tj;
 71             if(dfs(step+1))
 72                 return true;
 73             pm[(i+2)%4](G,mx[tj]);
 74         }
 75         return false;
 76 }
 77 int main()
 78 {
 79     //freopen("input.txt","r",stdin);
 80     int i,j;
 81     while(cin>>G[0][2]&&G[0][2])
 82     {
 83 //*******************************************************
 84 //      input data
 85         cin>>G[0][4];
 86         cin>>G[1][2]>>G[1][4];
 87         for(i=0;i<7;i++)
 88             cin>>G[2][i];
 89         cin>>G[3][2]>>G[3][4];
 90         for(i=0;i<7;i++)
 91             cin>>G[4][i];
 92         cin>>G[5][2]>>G[5][4]>>G[6][2]>>G[6][4];    
 93 //***************inpute end********************************
 94 
 95 
 96 //*************set point**************************************
 97         pm[0]=up;
 98         pm[1]=right;
 99         pm[2]=down;
100         pm[3]=left;
101 //***********************************************************
102 
103 
104 //*****************control dfs**********************************
105         deep=8-check(G);
106         if(deep==0)
107 
108             cout<<"No moves needed"<<endl<<G[2][2]<<endl;
109         else
110         {
111             while(!dfs(0))deep++;
112             for(i=0;i<cs;i++)
113                 cout<<opt[ans[i]][bs[i]];
114             cout<<endl<<G[2][2]<<endl;
115         }
116     }
117     return 0;
118 }

 

 

HDU 2234 无题I

ida*

     1.估价函数

       计算每一行至少需要到步数能移成四个一样的数字,并累加起来得到s1

                    计算每一列至少需要到步数能移成四个一样的数字,并累加起来得到s2

       s=min(s1,s2)

                    返回 (s+3)/4                原因在于   每移动一次能改变四个数字 所以除以4  

 2。写好四个移动函数,ida*搜索就行了。

 代码在此

View Code
  1 #include<iostream>
  2 #include<cstring>
  3 #include<stdio.h>
  4 #define inf 100000
  5 using namespace std;
  6 int block[4][4];
  7 int ans;
  8 void Left(int (*b)[4],int row)
  9 {
 10     int t=b[row][0],i;
 11     for(i=0;i<3;i++)
 12         b[row][i]=b[row][i+1];
 13     b[row][3]=t;
 14 }
 15 void Right(int (*b)[4],int row)
 16 {
 17     int t=b[row][3],i;
 18     for(i=3;i>0;i--)
 19         b[row][i]=b[row][i-1];
 20     b[row][0]=t;
 21 }
 22 void Up(int (*b)[4],int col)
 23 {
 24     int i,t=b[0][col];
 25     for(i=0;i<3;i++)
 26         b[i][col]=b[i+1][col];
 27     b[3][col]=t;
 28 }
 29 
 30 void Down(int (*b)[4],int col)
 31 {
 32     int i,t=b[3][col];
 33     for(i=3;i>0;i--)
 34         b[i][col]=b[i-1][col];
 35     b[0][col]=t;
 36 }
 37 int h(int (*b)[4])
 38 {
 39     int i,j,tmp,ans=inf;
 40     int hs[5],cnt;
 41     tmp=0;
 42     for(i=0;i<4;i++)
 43     {
 44         cnt=0;
 45         memset(hs,0,sizeof(hs));
 46         for(j=0;j<4;j++)
 47             hs[b[i][j]]++;
 48         for(j=1;j<=4;j++)
 49             cnt=max(cnt,hs[j]);
 50             
 51             tmp+=4-cnt;
 52     }
 53     ans=min(ans,tmp);
 54     tmp=0;
 55     for(j=0;j<4;j++)
 56     {
 57         cnt=0;
 58         memset(hs,0,sizeof(hs));
 59         for(i=0;i<4;i++)
 60             hs[b[i][j]]++;
 61         for(i=1;i<=4;i++)
 62             cnt=max(cnt,hs[i]);
 63             tmp+=4-cnt;
 64     }
 65     ans=min(ans,tmp);
 66     return (ans+3)/4;
 67 }
 68 
 69 bool dfs(int step)
 70 {
 71     int hz=h(block);
 72     if(hz==0)return true;
 73     if(step+hz>ans)
 74         return false;
 75     int i;
 76     for(i=0;i<4;i++)
 77     {
 78         Left(block,i);
 79         if(dfs(step+1))return true;
 80         Right(block,i);
 81     }
 82 
 83     for(i=0;i<4;i++)
 84     {
 85         Right(block,i);
 86         if(dfs(step+1))return true;
 87         Left(block,i);
 88     }
 89 
 90     for(i=0;i<4;i++)
 91     {
 92         Up(block,i);
 93         if(dfs(step+1))return true;
 94         Down(block,i);
 95     }
 96 
 97     for(i=0;i<4;i++)
 98     {
 99         Down(block,i);
100         if(dfs(step+1))return true;
101         Up(block,i);
102     }
103     return false;
104 }
105 int main()
106 {
107     //freopen("input.txt","r",stdin);
108     int T,i,j;
109     cin>>T;
110     while(T--)
111     {
112         for(i=0;i<4;i++)
113             for(j=0;j<4;j++)
114                 scanf("%d",&block[i][j]);
115         ans=0;
116         while(ans<=5&&!dfs(0))
117             ans++;
118         if(ans<6)
119             cout<<ans<<endl;
120         else
121             cout<<-1<<endl;
122     }
123     return 0;
124 }

 

HDU 1560 DNA sequence

继续ida*

1.估价函数

    返回 处理到当前状态时,还剩下的最长的字符串的长度。

    检举当前的可能的字符x, x={ATCG}四种。  如果对于所用序列,如果开始是x,则开始指针向的移动,如果没有一样的,则说明当前不可能是x,继续下一个。


代码在此:

View Code
 1 #include<iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 using namespace std;
 5 char str[10][10],ans[100];
 6 int N,ns[100];
 7 int len[10];
 8 int step;
 9 char bz[]="AGCT";
10 int h()
11 {
12     int i,p=0;
13     for(i=0;i<N;i++)
14         if(len[i]-ns[i]>p)
15             p=len[i]-ns[i];
16             return p;
17 }
18 bool dfs(int k)
19 {
20     
21     int i,j,ht=h();
22     if(ht==0)return true;
23     if(k+ht>step)
24         return false;
25     int sta[10],top=0;
26     bool flag;
27     for(i=0;i<4;i++)               //枚举当前可能的
28     {
29         flag=false;
30         for(j=0;j<N;j++)
31             if(str[j][ns[j]]==bz[i])
32                 {
33                     flag=true;
34                     ns[j]++;      
35                     sta[top++]=j;
36                }
37         if(flag)
38         if(dfs(k+1))
39             return true;
40         for(j=0;j<top;j++)
41         {
42             ns[sta[j]]--;
43         }
44         top=0;
45     }
46     return false;
47 }
48 int main()
49 {
50     //freopen("input.txt","r",stdin);
51     int T,i;
52     cin>>T;
53     while(T--)
54     {
55         cin>>N;
56         for(i=0;i<N;i++)
57             cin>>str[i];
58         step=0;
59         for(i=0;i<N;i++)
60             len[i]=strlen(str[i]);
61 
62         memset(ns,0,sizeof(ns));
63         while(!dfs(0))
64         {
65             memset(ns,0,sizeof(ns));
66             step++;
67         }
68         cout<<step<<endl;
69     }
70     
71     return 0;
72 }

 

HDU 1813  Escape from Tetris

这题一看没思路啊。结果是字典序枚举指令"east","north","south","west"。  总之是 ida*

1. 估价函数:

      首先,求出各个点到边上的最小步数。  把边界的空点加入队列进行 bfs。用个数组记录下

      然后,所有的空点一起走一步,

      在此过程中,返回这些点中到边上的步数中最大的(即上边用数组记录下的。

View Code
  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<vector>
  5 #include<queue>
  6 using namespace std;
  7 int N,sp;
  8 char G[12][12];
  9 int mx[]={0,-1,1,0};
 10 int my[]={1,0,0,-1};
 11 char outstr[4][6]={"east","north","south","west"};
 12 int ans[100];
 13 struct point
 14 {
 15     int x,y;
 16     bool stop;
 17     point(int a=0,int b=0):x(a),y(b){stop=false;}
 18 };
 19 vector<point> start;
 20 queue<point> Q;
 21 bool isedg(int x,int y)
 22 {
 23     if(x==0||x==N-1||y==0||y==N-1)
 24         return true;
 25     return false;
 26 }
 27 int minstep[12][12];
 28 int h()
 29 {
 30     int maxn=0,n=start.size(),i;
 31     for(i=0;i<n;i++)
 32         if(maxn<minstep[start[i].x][start[i].y])
 33             maxn=minstep[start[i].x][start[i].y];
 34     return maxn;
 35 }
 36 bool dfs(int k)
 37 {
 38     int hz=h();
 39     if(hz==0)return true;
 40     if(k+hz>sp)return false;
 41     int i,j,n=start.size(),tx,ty;
 42     vector<point> tmp(start);
 43     bool flag;
 44     for(i=0;i<4;i++)
 45     {
 46         flag=false;
 47         for(j=0;j<n;j++)
 48             if(!start[j].stop)
 49             {
 50             flag=true;
 51             tx=start[j].x+mx[i];
 52             ty=start[j].y+my[i];
 53             if(G[tx][ty]=='1')
 54                 continue;
 55             if(isedg(tx,ty))         //判断是不是到了边上
 56                 start[j].stop=true;
 57             start[j].x=tx;
 58             start[j].y=ty;
 59             }
 60             if(!flag)
 61                 return true;
 62             else
 63             { 
 64                 ans[k]=i;
 65                 if(dfs(k+1))    
 66                    return true;
 67             }
 68         for(int var=0;var<n;var++)
 69             start[var]=tmp[var];
 70     }
 71     return false;
 72 }
 73 void bfs()             //广搜出各个点最少能到边上的距离
 74 {
 75     int i,tx,ty;
 76     point t;
 77     while(!Q.empty())
 78     {
 79         t=Q.front();Q.pop();
 80         for(i=0;i<4;i++)
 81         {
 82             tx=t.x+mx[i];
 83             ty=t.y+my[i];
 84             if(tx>=0&&tx<N&&ty>=0&&ty<N)
 85                 if(G[tx][ty]=='0')
 86                 if(minstep[tx][ty]>minstep[t.x][t.y]+1)
 87                 {
 88                     minstep[tx][ty]=minstep[t.x][t.y]+1;
 89                     Q.push(point(tx,ty));
 90                 }
 91         }
 92     }
 93 
 94 }
 95 int main()
 96 {
 97     //freopen("input.txt","r",stdin);
 98     int i,j;
 99     bool isfirst=true;
100     while(cin>>N)
101     {
102         start.clear();
103         while(!Q.empty())Q.pop();
104         memset(minstep,127,sizeof(minstep));
105         for(i=0;i<N;i++)
106             cin>>G[i];
107         for(i=0;i<N;i++)
108             for(j=0;j<N;j++)
109                 if(G[i][j]=='0')
110                     if(!isedg(i,j))
111                       start.push_back(point(i,j));  //将中间的空点装入数组,以备深搜
112                     else
113                     {
114                         minstep[i][j]=0;          //将边界空点装入队列,以备广搜
115                         Q.push(point(i,j));
116                     }
117         bfs();
118        sp=0;
119        while(!dfs(0))
120            sp++;
121        if(!isfirst)
122            cout<<endl;
123        isfirst=false;
124        for(j=0;j<sp;j++)
125            cout<<outstr[ans[j]]<<endl;
126     }
127     return 0;
128 }

 

  HDU 2918 Tobo or not Tobo

  这个还是ida*

1.估价函数:

     (曼哈顿距离+3)/4         除以4是因为,每转一次会改变四方块,也就是曼哈顿距离会变4

然后我写了顺时针转和逆时针转的函数。

  又把四旋钮的所控制的四个方块,分别存到数组里 

ida*   搜索吧

 

代码在此:

View Code
 1 #include<iostream>
 2 #include<stdio.h>
 3 using namespace std;
 4 int board[10][10];
 5 int lim;
 6 int *p[4][4];
 7 int ans;
 8 void (*rot[2])(int *p[]); 
 9 void AntiClockWise(int *p[])
10 {
11     int t=*p[0],i;
12     for(i=0;i<3;i++)
13         *p[i]=*p[i+1];
14     *p[3]=t;
15 }
16 void ClockWise(int *p[])
17 {
18     int t=*p[3],i;
19     for(i=3;i>0;i--)
20         *p[i]=*p[i-1];
21     *p[0]=t;
22 }
23 void set_point()
24 {
25     rot[0]=ClockWise;
26     rot[1]=AntiClockWise;
27     p[0][0]=&board[0][0]; p[0][1]=&board[0][1]; p[0][2]=&board[1][1]; p[0][3]=&board[1][0];
28     p[1][0]=&board[0][1]; p[1][1]=&board[0][2]; p[1][2]=&board[1][2]; p[1][3]=&board[1][1];
29     p[2][0]=&board[1][0]; p[2][1]=&board[1][1]; p[2][2]=&board[2][1]; p[2][3]=&board[2][0];
30     p[3][0]=&board[1][1]; p[3][1]=&board[1][2]; p[3][2]=&board[2][2]; p[3][3]=&board[2][1];
31 }
32 void show_state()
33 {
34     int i,j;
35     for(i=0;i<3;i++)
36     {
37         for(j=0;j<3;j++)
38             cout<<board[i][j];
39         cout<<endl;
40     }
41     cout<<endl;
42 }
43 int h()
44 {
45     int i,j,tx,ty,s=0;
46     for(i=0;i<3;i++)
47         for(j=0;j<3;j++)
48         {
49             tx=(board[i][j]-1)/3;
50             ty=(board[i][j]-1)%3;
51             s+=abs(i-tx)+abs(j-ty);
52         }
53         return (s+3)/4;
54 }
55 bool dfs(int deep)
56 {
57     int i,j,d=h();
58     if(d==0)return true;
59     if(d+deep>ans)return false;
60     for(i=0;i<4;i++)
61         for(j=0;j<2;j++)
62         {
63             rot[j](p[i]);
64             if(dfs(deep+1))return true;
65             rot[j^1](p[i]);
66         }
67     return false;
68 }
69 int main()
70 {
71     //freopen("input.txt","r",stdin);
72     int i,j,sum,cs=0;
73     set_point();
74     while(scanf("%1d",&lim))
75     {
76         cs++;
77         sum=0;
78         for(i=0;i<3;i++)
79             for(j=0;j<3;j++)
80             {
81                 scanf("%1d",&board[i][j]);
82                 sum+=board[i][j];
83             }
84             sum+=lim;
85             if(sum==0)break;
86             //show_state();
87             ans=0;
88            while(ans<=lim&&!dfs(0))
89                ans++;
90            if(ans>lim)
91                printf("%d. %d\n",cs,-1);
92            else
93                printf("%d. %d\n",cs,ans);
94     }
95     return 0;
96 }

 

HDU 3459 Rubik 2×2×2

二阶段魔方问题。  ida*

估价函数:

在原点的那个方块是不动的,所心左,下,后三个面的颜色是确定的。 h()函数

先统计 这三个面上各自不应该出现的颜色的数量,并累加起来得到s。然后返回(s+3)/4   因为第次旋转会改变这三个面上最多4块的面积。

我写的这个暴力代码,基本是不用循环的。 希望能找到一定的规律以减少代码量。

代码在此:

View Code
  1 #include<iostream>
  2 #include<stdio.h>
  3 using namespace std;
  4 char G[6][9];
  5 int ans;
  6 char opt[4]="XYZ";
  7 char sto[200];
  8 void(*p[3])();
  9 void x_turn()
 10 {
 11     char a,b;
 12     a=G[4][3];
 13     b=G[5][3];
 14     G[5][3]=G[3][3]; G[4][3]=G[2][3];
 15     G[3][3]=G[1][3]; G[2][3]=G[0][3];
 16     G[1][3]=G[2][6]; G[0][3]=G[3][6];
 17     G[2][6]=b;       G[3][6]=a;
 18     char t=G[2][4];
 19     G[2][4]=G[2][5]; G[2][5]=G[3][5];
 20     G[3][5]=G[3][4]; G[3][4]=t;
 21 }
 22 void y_turn()
 23 {
 24     char a=G[2][6],b=G[2][7];
 25     int i;
 26     for(i=7;i>1;i-=2)
 27     {
 28         G[2][i]=G[2][i-2];
 29         G[2][i-1]=G[2][i-3];
 30     }
 31     G[2][1]=b; G[2][0]=a;
 32     char t=G[0][2];
 33     G[0][2]=G[0][3]; G[0][3]=G[1][3];
 34     G[1][3]=G[1][2]; G[1][2]=t;
 35 }
 36 void z_turn()
 37 {
 38     char a=G[1][2],b=G[1][3];
 39     G[1][2]=G[2][4]; G[1][3]=G[3][4];
 40     G[2][4]=G[4][3]; G[3][4]=G[4][2];
 41     G[4][3]=G[3][1]; G[4][2]=G[2][1];
 42     G[3][1]=a;       G[2][1]=b;
 43     char t=G[2][2];
 44     G[2][2]=G[2][3]; G[2][3]=G[3][3];
 45     G[3][3]=G[3][2]; G[3][2]=t;
 46 }
 47 void set_point()
 48 {
 49     p[0]=x_turn;
 50     p[1]=y_turn;
 51     p[2]=z_turn;
 52 }
 53 int h()
 54 {
 55     int sum=0;
 56     char a;
 57     a=G[3][0];
 58     if(G[3][1]!=a)sum++; if(G[2][0]!=a)sum++; if(G[2][1]!=a)sum++;
 59     a=G[5][2];
 60     if(G[5][3]!=a)sum++; if(G[4][2]!=a)sum++; if(G[4][3]!=a)sum++;
 61     a=G[3][7];
 62     if(G[3][6]!=a)sum++; if(G[2][6]!=a)sum++; if(G[2][7]!=a)sum++;
 63     return (sum+3)/4;
 64 }
 65 bool dfs(int deep)
 66 {
 67     int i;    
 68     int hz=h();
 69     if(hz==0)return true;
 70     if(deep+h()>ans)return false;
 71     char tmp[6][9];
 72     memcpy(tmp,G,sizeof(G));
 73     for(i=0;i<3;i++)
 74     {
 75         p[i]();
 76         sto[deep]=i;
 77         if(dfs(deep+1)) 
 78             return true;
 79         memcpy(G,tmp,sizeof(tmp));
 80     }
 81     return false;
 82 }
 83 int main()
 84 {
 85     //freopen("input.txt","r",stdin);
 86     int i;
 87     bool flag;
 88     char ps[6][9];
 89     
 90     set_point();
 91     while(true)
 92     {
 93         flag=false;
 94         for(i=0;i<6;i++)
 95             cin>>G[i];
 96         if(G[2][2]=='.')
 97             break;
 98         memcpy(ps,G,sizeof(G));
 99         ans=0;
100         while(!dfs(0))ans++;
101         memcpy(G,ps,sizeof(G));
102         for(i=0;i<ans;i++)
103             putchar(opt[sto[i]]);
104         putchar('\n');
105     }
106     return 0;
107 }

 

ida*也就这些了。

ida* A*  dfs比较

        A*算法 框架:

        估价函数: 

        状态存储: 

           判重:   

        就是bfs了。

        记录路径

            A* 是要用优先队列了。STL

 

ida*:

              估价函数h();

       bool    dfs(deep)

                   {

                            int hz=h();

                            if(hz==0)return true;

                             if(hz+deep>ans)return false;

                           计算  下一个状态。。if(dfs(deep+1))return true;

                              恢复环境。

       }

int main()

{

        读入数据;

   ans=0;

       while(!dfs(0)) ans++;

    cout<<ans<<endl;

}

 

ida*与A*相比,不用记录那么多状态,也不用判重。 如果问题的状态很多那就不能A*了

ida* 重复搜索很多。

ida*与普通dfs相比:

   有效的控制了深度,避免在一个方向上过度搜索。

于是,在问题的状态很多,而且深度可控制时可以用ida*

 

 估价函数的设计:

 算曼哈顿距离,还很常用。然后就尽量挖题里的限制吧。   有时个看似不起眼的估价,作用很大的。

 

状态存储和判重:

   康托。 hash   set map

STL的效率不怎么样啊。

注意代码不要出现中文空格啊,上次一不小心……

 

转载于:https://www.cnblogs.com/wyg031113/archive/2012/10/07/2713724.html

Architecting Modern Web Applications with ASP.NET Core and Azure. .NET Core and ASP.NET Core offer several advantages over traditional .NET development. You should use .NET Core for your server applications if some or all of the following are important to your application’s success: • Cross-platform support • Use of microservices • Use of Docker containers • High performance and scalability requirements • Side-by-side versioning of .NET versions by application on the same server Traditional .NET applications can and do support these requirements, but ASP.NET Core and .NET Core have been optimized to offer improved support for the above scenarios. More and more organizations are choosing to host their web applications in the cloud using services like Microsoft Azure. You should consider hosting your application in the cloud if the following are important to your application or organization: • Reduced investment in data center costs (hardware, software, space, utilities, etc.) • Flexible pricing (pay based on usage, not for idle capacity) • Extreme reliability • Improved app mobility; easily change where and how your app is deployed • Flexible capacity; scale up or down based on actual needs Building web applications with ASP.NET Core, hosted in Azure, offers many competitive advantages over traditional alternatives. ASP.NET Core is optimized for modern web application development practices and cloud hosting scenarios. In this guide, you’ll learn how to architect your ASP.NET Core applications to best take advantage of these capabilities.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值