HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041

主要内容是BFS,A*,IDA*,还有一道K短路的,.....木做,本来1009是说要用迭代加深做,但是我在他讲之前就用BFSA了,虽然很耗时,但还是过了,10000MS的时限,我8000+MS.......

1001 Eight  八数码问题

先把代码放上来

题目网址: http://acm.hdu.edu.cn/showproblem.php?pid=1043

500MS 3524K 3183 B
  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<queue>

  6 using namespace std;

  7 class  Node

  8 {

  9 public:

 10     int maze[3][3];   //八数码具体情况

 11     int h,g;    //两个估价函数

 12     int x,y;   //空位的位置

 13     int Hash;   //HASH值

 14     bool operator<(const Node n1)const{     //优先队列第一关键字为h,第二关键字为g

 15         return h!=n1.h?h>n1.h:g>n1.g;

 16     }

 17     bool check()     //判断是否合法

 18     {    

 19         if(x>=0&&x<3&&y>=0&&y<3)

 20             return true;

 21         return false;

 22     }

 23 }s,u,v;

 24 int HASH[9]={1,1,2,6,24,120,720,5040,40320};   //HASH的权值

 25 int des=322560;   //目标情况的HASH值

 26 int vis[400000];            //判断状态已遍历,初始为-1,否则为到达这步的转向

 27 int pre[400000];        //路径父节点

 28 int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}};   //四个方向

 29 int get_hash(Node tmp)     //获得HASH值

 30 {    

 31     int a[9],k=0;

 32     for(int i=0;i<3;i++)

 33         for(int j=0;j<3;j++)

 34             a[k++]=tmp.maze[i][j];

 35     int res=0;

 36     for(int i=0;i<9;i++){

 37         int k=0;

 38         for(int j=0;j<i;j++)

 39             if(a[j]>a[i])

 40                 k++;

 41         res+=HASH[i]*k;

 42     }

 43     return res;

 44 }

 45 bool isok(Node tmp){    //求出逆序对,判断是否有解

 46     int a[9],k=0;

 47     for(int i=0;i<3;i++)

 48         for(int j=0;j<3;j++)

 49             a[k++]=tmp.maze[i][j];

 50     int sum=0;

 51     for(int i=0;i<9;i++)

 52         for(int j=i+1;j<9;j++)

 53             if(a[j]&&a[i]&&a[i]>a[j])

 54                 sum++;

 55     return !(sum&1);    //由于目标解为偶数,所以状态的逆序数为偶数才可行

 56 }

 57 int get_h(Node tmp){   //获得估价函数H

 58     int ans=0;

 59     for(int i=0;i<3;i++)

 60         for(int j=0;j<3;j++)

 61             if(tmp.maze[i][j])

 62                 ans+=abs(i-(tmp.maze[i][j]-1)/3)+abs(j-(tmp.maze[i][j]-1)%3);

 63     return ans;

 64 }

 65 void astar(){    //搜索

 66     priority_queue<Node>que;    //优先队列

 67     que.push(s);

 68     while(!que.empty())

 69     {

 70         u=que.top();

 71         que.pop();   //出队

 72         for(int i=0;i<4;i++)

 73         {

 74             v=u;

 75             v.x+=way[i][0];

 76             v.y+=way[i][1];

 77             if(v.check())

 78             {

 79                 swap(v.maze[v.x][v.y],v.maze[u.x][u.y]);   //将空位和相邻位交换

 80                 v.Hash=get_hash(v);             //得到HASH值

 81                 if(vis[v.Hash]==-1)//判断是否已遍历且是否可行

 82                 {   

 83                     vis[v.Hash]=i;           //保存方向

 84                     v.g++;;                  //代价++

 85                     pre[v.Hash]=u.Hash;     //保存v的父节点u

 86                     v.h=get_h(v);           //得到新的估价函数H

 87                     que.push(v);     //入队

 88                 }

 89                 if(v.Hash==des)

 90                     return ;

 91             }

 92         }

 93     }

 94 }

 95 void print()

 96 {

 97     string ans;

 98     char wu[4]={'r','l','d','u'};

 99     ans.clear();

100     int nxt=des;

101     while(pre[nxt]!=-1)        //从终点往起点找路径

102     {  

103         ans+=wu[vis[nxt]];

104         nxt=pre[nxt];   //上一个父节点

105     }

106     for(int i=ans.size()-1;i>=0;i--)

107         printf("%c",ans[i]);

108     printf("\n");

109 }

110 int main()

111 {

112     char str[100];

113     while(gets(str)!=NULL)      

114     {

115         int k=0;

116         memset(vis,-1,sizeof(vis));

117         memset(pre,-1,sizeof(pre));

118         for(int i=0;i<3;i++)

119             for(int j=0;j<3;j++)

120                 {

121                 if((str[k]<='9'&&str[k]>='0')||str[k]=='x')

122                 {

123                     if(str[k]=='x')

124                     {

125                         s.maze[i][j]=0;

126                         s.x=i;

127                         s.y=j;

128                     }

129                     else

130                         s.maze[i][j]=str[k]-'0';

131                 }

132                 else

133                     j--;

134                 k++;

135             }

136         if(!isok(s))      //起始状态不可行

137         {   

138             printf("unsolvable\n");

139             continue;

140         }

141         s.Hash=get_hash(s);

142         if(s.Hash==des)    

143         {  

144             printf("\n");

145             continue;

146         }

147         vis[s.Hash]=-2;

148         s.g=0;s.h=get_h(s);

149         astar();   //A*

150         print();   //打印路径

151     }

152     return 0;

153 }

 

  1 #include <iostream>

  2 #include <stdio.h>

  3 #include <string.h>

  4 #include <string>

  5 #include <algorithm>

  6 #include <queue>

  7 using namespace std;

  8 class A

  9 {

 10 public:

 11     int a[3][3];

 12     int h,g;

 13     int x,y;

 14     int has;

 15     bool operator<(const A n)const{return h!=n.h?h>n.h:g>n.g;}

 16     bool check()

 17     {

 18         if (x>=0&&x<=2&&y>=0&&y<=2)

 19             return true;

 20         return false;

 21     }

 22 }s,w,r;

 23 int H[9]={1,1,2,6,24,120,720,5040,40320};

 24 int des=322560;

 25 int v[400000];

 26 int p[400000];

 27 int d[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

 28 

 29 bool ok(A c)

 30 {

 31     int q[9],k=0,i,j,sum=0;

 32     for(i=0;i<3;i++)

 33         for(j=0;j<3;j++)

 34         q[k++]=c.a[i][j];

 35     for(i=0;i<9;i++)

 36         for(j=i+1;j<9;j++)

 37         if(q[j]&&q[i]&&q[i]>q[j])

 38         sum++;

 39     return !(sum&1);

 40 }

 41 

 42 int gethas(A c)

 43 {

 44    int q[9],k=0,i,j,sum=0;

 45     for(i=0;i<3;i++)

 46         for(j=0;j<3;j++)

 47         q[k++]=c.a[i][j];

 48     for(i=0;i<9;i++)

 49     {

 50         int o=0;

 51         for(j=0;j<i;j++)

 52             if(q[j]>q[i])

 53                o++;

 54         sum+=H[i]*o;

 55     }

 56     return sum;

 57 }

 58 

 59 int geth(A c)

 60 {

 61     int sum=0,i,j;

 62     for(i=0;i<3;i++)

 63         for(j=0;j<3;j++)

 64         if(c.a[i][j])

 65           sum+=abs(i-(c.a[i][j]-1)/3)+abs(j-(c.a[i][j]-1)%3);

 66     return sum;

 67 }

 68 

 69 void astar()

 70 {

 71     int i;

 72     priority_queue<A>f;

 73     f.push(s);

 74     while(!f.empty())

 75     {

 76         w=f.top();

 77         f.pop();

 78         for(i=0;i<4;i++)

 79         {

 80             r=w;

 81             r.x+=d[i][0];

 82             r.y+=d[i][1];

 83             if(r.check())

 84             {

 85                 swap(r.a[w.x][w.y],r.a[r.x][r.y]);

 86                 r.has=gethas(r);

 87                 if(v[r.has]==-1)

 88                 {

 89                     v[r.has]=i;

 90                     r.g++;

 91                     p[r.has]=w.has;

 92                     r.h=geth(r);

 93                     f.push(r);

 94                 }

 95                 if(r.has==des)

 96                     return ;

 97             }

 98         }

 99     }

100 }

101 

102 void print()

103 {

104     string str;

105     char wu[4]={'r','l','d','u'};

106     str.clear();

107     int next=des,i;

108     while(p[next]!=-1)

109     {

110         str+=wu[v[next]];

111         next=p[next];

112     }

113     for(i=str.size()-1;i>=0;i--)

114         putchar(str[i]);

115     printf("\n");

116 }

117 

118 int main()

119 {

120     char b[100];

121     int i,j,k;

122     while(gets(b)!=NULL)

123     {

124        memset(v,-1,sizeof(v));

125        memset(p,-1,sizeof(p));

126        k=0;

127        for(i=0;i<3;i++)

128             for(j=0;j<3;j++)

129             {

130                 if(b[k]=='x')

131                 {

132                     s.a[i][j]=0;

133                     s.x=i;

134                     s.y=j;

135                 }

136                 else if(b[k]>='0'&&b[k]<='9')

137                     s.a[i][j]=b[k]-'0';

138                 else

139                     j--;

140                 k++;

141             }

142 

143         if(!ok(s))

144         {

145             printf("unsolvable\n");

146             continue;

147         }

148         s.has=gethas(s);

149         if(s.has==des)

150         {

151             printf("\n");

152             continue;

153         }

154         v[s.has]=-2;

155         s.g=0;

156         s.h=geth(s);

157         astar();

158         print();

159     }

160 }
View Code

  

 

 

 1006    The Rotation Game  

第二题  IDA*算法,感觉比上面那个简单

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1667

296MS 300K 1895 B
 1 #include <stdio.h>

 2 #include <iostream>

 3 #include <string.h>

 4 #include <algorithm>

 5 using namespace std;

 6 int maxx(int x,int y,int z)  {return max(max(x,y),z);}   //三个数的最大值

 7 int  a[9][8]={

 8     0,0,0,0,0,0,0,0,

 9     0,1,3,7,12,16,21,23,

10     0,2,4,9,13,18,22,24,

11     0,11,10,9,8,7,6,5,

12     0,20,19,18,17,16,15,14,

13     0,24,22,18,13,9,4,2,

14     0,23,21,16,12,7,3,1,

15     0,14,15,16,17,18,19,20,

16     0,5,6,7,8,9,10,11

17 };    //每一纵行和横行的编号

18 int re[9]={0,6,5,8,7,2,1,4,3};    //往回移对应的编号

19 int mid[9]={0,7,8,9,12,13,16,17,18};   //中间的8个数的编号

20 char lu[]="OABCDEFGH";    //路径

21 int b[28];    //现状

22 char father[300];       //记录父节点的编号

23 int dep;    //允许的深度

24 

25 int geth(int b[28])   //获得H值

26 {

27     int i,w[4];

28     memset(w,0,sizeof(w));

29     for(i=1;i<=8;i++)

30         w[b[mid[i]]]++;

31     return 8-maxx(w[1],w[2],w[3]);

32 }

33 

34 int IDA(int g)

35 {

36     int i,H,t,j;

37     if(g>=dep)

38         return 0;

39     for(i=1;i<=8;i++)

40     {

41         t=b[a[i][1]];

42         for(j=1;j<=6;j++)

43             b[a[i][j]]=b[a[i][j+1]];

44         b[a[i][7]]=t;

45         father[g]=i;    //记录父节点

46         H=geth(b);    //获得最新的H

47         if(!H)

48             return 1;

49         if(g+H<dep && IDA(g+1))    //A*剪枝

50             return 1;

51         t=b[a[re[i]][1]];     //回到上一步

52         for(j=1;j<=6;j++)

53             b[a[re[i]][j]]=b[a[re[i]][j+1]];

54         b[a[re[i]][7]]=t;

55     }

56     return 0;

57 }

58 

59 int main()

60 {

61     int i;

62     while(~scanf("%d",&b[1])&&b[1])

63     {

64         for(i=2;i<=24;i++)

65             scanf("%d",&b[i]);

66         dep=geth(b);

67         if(!dep)     //不需要移动

68         {

69             printf("No moves needed\n");

70             printf("%d\n",b[8]);

71             continue;

72         }

73         while(!IDA(0))

74             dep++;

75         for(i=0;i<=dep-1;i++)

76             printf("%c",lu[father[i]]);

77         printf("\n%d\n",b[8]);

78     }

79     return 0;

80 }

 

你可能感兴趣的:(game)