2016.6.10 深度优先搜索练习

1.1004 四子连棋

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 黄金 Gold

题目描述 Description

在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。

 
 

输入描述 Input Description

从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。

输出描述 Output Description

用最少的步数移动到目标棋局的步数。

样例输入 Sample Input

BWBO
WBWB
BWBW
WBWO

样例输出 Sample Output

5

  1 #define N 5
  2 #include<iostream>
  3 using namespace std;
  4 #include<cstdio>
  5 char jz[N][N];
  6 struct Q{
  7     int x,y;
  8 }q[2];
  9 int xx[]={1,-1,0,0};
 10 int yy[]={0,0,1,-1};
 11 long long sum=100;/*假设一个最大步数,一开始设定太大了,直接爆了栈空间*/
 12 int t=-1;
 13 bool check()
 14 {
 15     for(int i=1;i<=4;++i)
 16     {
 17         char s=jz[i][1];
 18         bool biaozhi=true;
 19         for(int j=2;j<=4;++j)
 20         {
 21             if(jz[i][j]!=s)
 22             {
 23                 biaozhi=false;
 24                 break;
 25              }
 26         }
 27         if(biaozhi) return true;
 28     }
 29     for(int i=1;i<=4;++i)
 30     {
 31         char s=jz[1][i];
 32         bool biaozhi=true;
 33         for(int j=2;j<=4;++j)
 34         {
 35             if(jz[j][i]!=s)
 36             {
 37                 biaozhi=false;
 38                 break;
 39              }
 40         }
 41         if(biaozhi) return true;
 42     }
 43     bool biaozhi=true;
 44     char s=jz[1][1];
 45     for(int i=2;i<=4;++i)
 46     {
 47         if(jz[i][i]!=s)
 48         {
 49             biaozhi=false;
 50             break;
 51         }
 52     }
 53     if(biaozhi) return true;
 54     biaozhi=true;
 55     s=jz[1][4];
 56     for(int i=2;i<=4;++i)
 57     {
 58         if(jz[i][5-i]!=s)
 59         {
 60             biaozhi=false;
 61             break;
 62         }
 63     }
 64     if(biaozhi) return true;
 65     return false;
 66 }
 67 void dfs(bool fla,long long bushu)
 68 {
 69     if(bushu>=sum) return;
 70     if(check())
 71     {
 72         sum=min(sum,bushu);
 73         return;
 74     }
 75     for(int i=0;i<2;++i)
 76     {
 77         for(int j=0;j<4;++j)
 78         {
 79             int x1=q[i].x+xx[j],y1=q[i].y+yy[j];
 80             if(x1>=1&&x1<=4&&y1>=1&&y1<=4)
 81             {
 82                 if(fla&&jz[x1][y1]==‘W‘)
 83                 {
 84                   swap(jz[x1][y1],jz[q[i].x][q[i].y]);
 85                   swap(x1,q[i].x);
 86                   swap(y1,q[i].y);
 87                   dfs(!fla,bushu+1);
 88                   swap(jz[x1][y1],jz[q[i].x][q[i].y]);
 89                   swap(x1,q[i].x);
 90                   swap(y1,q[i].y);
 91                 }
 92                 if(!fla&&jz[x1][y1]==‘B‘)
 93                 {
 94                   swap(jz[x1][y1],jz[q[i].x][q[i].y]);
 95                   swap(x1,q[i].x);
 96                   swap(y1,q[i].y);
 97                   dfs(!fla,bushu+1);
 98                   swap(jz[x1][y1],jz[q[i].x][q[i].y]);
 99                   swap(x1,q[i].x);
100                   swap(y1,q[i].y);
101                 }
102             }
103         }
104     }
105 }
106 int main()
107 {
108     for(int i=1;i<=4;++i)
109     {
110         scanf("%s",jz[i]+1);
111         for(int j=1;j<=4;++j)
112         {
113             if(jz[i][j]==‘O‘)
114             {
115               ++t;
116               q[t].x=i;q[t].y=j;
117             }
118         }
119     }
120     //swap(q[0],q[1]);
121     bool flag[]={true,false};
122        for(int j=0;j<2;++j)
123        dfs(flag[j],0);
124     cout<<sum<<endl;
125     return 0;
126 }

2.1008 选数

2002年NOIP全国联赛普及组

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 黄金 Gold

题目描述 Description

已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
    3+7+12=22  3+7+19=29  7+12+19=38  3+12+19=34。
  现在,要求你计算出和为素数共有多少种。
  例如上例,只有一种的和为素数:3+7+19=29)。

输入描述 Input Description

 键盘输入,格式为:
  n , k (1<=n<=20,k<n)
  x1,x2,…,xn (1<=xi<=5000000)

输出描述 Output Description

屏幕输出,格式为:
  一个整数(满足条件的种数)。

样例输入 Sample Input

4 3
3 7 12 19

样例输出 Sample Output

1

数据范围及提示 Data Size & Hint

(1<=n<=20,k<n)
(1<=xi<=5000000)

 1 /*顺便复习Miller_rabin算法*/
 2 #define N 21
 3 #include<iostream>
 4 using namespace std;
 5 #include<cstdio>
 6 #include<cstdlib>
 7 #include<ctime>
 8 typedef long long ll;
 9 int a[N],n,k;
10 ll ans=0;
11 void input()
12 {
13     scanf("%d%d",&n,&k);
14     for(ll i=1;i<=n;++i)
15       scanf("%d",&a[i]);
16 }
17 ll quick_mod(ll a,ll b,ll c)
18 {
19     ll ans=1;
20     a%=c;
21     while(b)
22     {
23         if(b&1)
24         {
25             b--;
26             ans=(ans*a)%c;;
27         }
28         a=(a*a)%c;
29         b>>=1;
30     }
31     return ans;
32 }
33 bool Miller_rabin(ll n)
34 {
35     if(n==2) return true;
36     if(n<=1||!(n&1)) return false;
37     ll u=n-1,t=0;
38     while(!(u&1))
39     {
40         u>>=1;
41         t++;
42     }
43     for(ll i=1;i<=10;++i)
44     {
45         ll x=rand()%(n-1)+1;
46         x=quick_mod(x,u,n);
47         for(ll j=0;j<t;++j)
48         {
49             ll y=quick_mod(x,2,n);
50             if(y==1&&x!=1&&x!=n-1)
51               return false;
52             x=y;
53         }
54         if(x!=1) return false;
55     }
56     return true;
57 }
58 void dfs(ll xh,ll sum,ll djg)
59 {
60     if(djg==k)
61     {
62         if(Miller_rabin(sum))
63           ans++;
64         return;
65     }
66     if(n-xh<k-djg) return;
67     for(ll i=1;i<=n;++i)
68     {
69         if(xh+i<=n) dfs(xh+i,sum+a[xh+i],djg+1);
70         else break;
71     }
72 }
73 int main()
74 {
75     srand(time(0));
76     input();
77     for(ll i=1;i<=n-k+1;++i)
78     {
79         dfs(i,a[i],1);
80     }
81     cout<<ans<<endl;
82     return 0;
83 }

3.1005 生日礼物

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 黄金 Gold

题目描述 Description

9月12日是小松的朋友小寒的生日。小松知道小寒特别喜欢蝴蝶,所以决定折蝴蝶作为给小寒的生日礼物。他来到了PK大学最大的一家地下超市,在超市里,小松找到了n种可以用来折纸的本子。每种类型的本子里有若干不同颜色的纸若干张,当然同种类型的本子一定是完全一样的,而不同种类型的本子不一定完全不一样。他统计了一下,这里总共有n种不同类型的可以用来折纸的本子,每种本子各有bi本,所有的纸中有m种颜色是小寒所喜欢的颜色。小松希望他折的每种颜色的蝴蝶的数目是一样的。换句话说,小松必须折m*k只蝴蝶,其中k代表每种颜色蝴蝶的数目,这个数由小松自己来决定。但是小松又不能浪费纸,也就是说他买的本子中,只要是小寒喜欢的颜色的纸都要被折成蝴蝶。于是问题来了,每种类型的本子应该各买多少本,才能折出这m*k只蝴蝶呢?当然,由于小松是个很懒的人,他希望折的蝴蝶数目越少越好,只要表达了心意就可以了(也就是不能1只也不折)。而如果小松总共必须折1000只以上的蝴蝶才能满足要求,那么他就宁愿换一种礼物的方案了。

输入描述 Input Description

输入的第一行包含2个整数n(1≤n8),m(1≤m10)。表示有n种不同类型的本子和m种小寒喜欢的颜色。接下来一个n*m的矩阵。第i行第j列的整数aij表示在第i种类型的本子中包含小寒喜欢的颜色j的纸有aij(1≤aij100)张。再接下来的一排n个整数b1bn,表示每种颜色的本子在超市中有多少本(1≤bi5)。

输出描述 Output Description

输出包含一个整数,表示小松最少需要折的蝴蝶数目,如果该数目超过1000,则输出”alternative!”。(由于可能存在多种买本子的方案,所以这里就不要求输出具体方案了)

样例输入 Sample Input

2 3

2 1 2

4 8 4

5 5

样例输出 Sample Output

36

  1 #define N 11
  2 #include<iostream>
  3 using namespace std;
  4 #include<cstdio>
  5 int b[N],jz[N][N],n,m,a[N];
  6 int flag=false;
  7 void input()
  8 {
  9     scanf("%d%d",&n,&m);
 10     for(int i=1;i<=n;++i)
 11       for(int j=1;j<=m;++j)
 12       scanf("%d",&jz[i][j]);
 13     for(int i=1;i<=n;++i)
 14     scanf("%d",&b[i]);
 15 }
 16 bool check(int xz)
 17 {
 18     for(int j=1;j<=m;++j)
 19       if(a[j]!=xz) return false;
 20     return true;
 21 }
 22 void dfs(int k,int xz)
 23 {
 24     if(check(xz))
 25     {
 26         flag=true;
 27         return;
 28     }
 29     if(k==n) return;
 30     for(int i=k+1;i<=n;++i)
 31     {
 32         int j;
 33         int fla=false;
 34       for(int l=0;l<=b[i];l++)
 35       {
 36           for(j=1;j<=m;++j)
 37         {
 38             a[j]+=l*jz[i][j];
 39             if(a[j]>xz)
 40             {
 41                 fla=true;
 42                 break;
 43             }
 44         }
 45         if(fla)
 46         {
 47             for(int g=1;g<=j;++g)
 48                  a[g]-=l*jz[i][g];
 49                break;
 50         }
 51         dfs(i,xz);
 52         if(flag) return;
 53         for(j=1;j<=m;++j)
 54         {
 55             a[j]-=jz[i][j]*l;
 56         }
 57       }
 58     }
 59 }
 60 int main()
 61 {
 62     input();
 63     int k;
 64     for(k=1;;++k)
 65     {
 66       int fla=false;
 67       for(int i=1;i<=n;++i)
 68       {
 69           int j;
 70       for(int l=0;l<=b[i];l++)
 71 /*枚举从0开始表示这个本子可以买,也可以不买*/
 72       {
 73           for(j=1;j<=m;++j)
 74         {
 75             a[j]+=l*jz[i][j];
 76             if(a[j]>k)
 77             {
 78                 fla=true;
 79                 break;
 80             }
 81         }
 82         if(fla)
 83         {
 84             for(int g=1;g<=j;++g)
 85                  a[g]-=l*jz[i][g];
 86                break;
 87         }
 88         dfs(i,k);
 89         for(j=1;j<=m;++j)
 90         {
 91             a[j]-=jz[i][j]*l;
 92         }
 93        }
 94       }
 95         if(k*m>1000)
 96         {
 97              printf("alternative!\n");
 98              return 0;
 99         }
100         if(flag) break;
101     }
102     printf("%d\n",m*k);
103     return 0;
104 }
时间: 2024-11-11 11:57:41

2016.6.10 深度优先搜索练习的相关文章

深度优先搜索与广度优先搜索算法理解

深度优先搜索算法和广度优先搜索算法是图论中两个有意思也很实用的算法,下面我们来看看这两个算法. 严书中,给出的利用深度优先搜索(Deep First Search)算法进行图的遍历伪码如下 1 Boolean visited[MAX]; //标志数组 2 Status (*VisitFunction)(int v); //访问函数 3 4 void DFSTraverse(Graph G, Status (*Visit)(int v)) 5 { 6 VisitFunction = Visit;

深度优先搜索思想初体验

1.求数字 1~n 的全排列 import java.util.Scanner ; public class Permutation{ //求数字 1~n 的全排列: int[] array ; int[] book ; int n ; public void permutation(int step){ // 深度优先搜索思想: if (step==n+1) { for (int i=1;i<=n;i++) { System.out.print(array[i] + " ")

深度优先搜索(DFS)

定义: (维基百科:https://en.wikipedia.org/wiki/Depth-first_search) 深度优先搜索算法(Depth-First-Search),是搜索算法的一种.是沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点.这一过程一直进行到已发现从源节点可达的所有节点为止.如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止(属于盲目搜索). 基

图算法系列-深度优先搜索与广度优先搜索

2.深度优先搜索 为了访问一个顶点,我们将它标记为已经访问过,然后递归的访问所有与子邻接的并且尚未标记的顶点,这就是深度优先搜索(DFS),DFS常用于解决路径问题. 比如下面的连通图,我们从顶点0开始对图进行探索 下面这个图显示了DFS处理时的递归调用树. DFS可以解决的问题:1)环检测:一个图中有环吗?该图是森林吗?2)简单路径:给定两个顶点,是否存在一条连接他们的路径3)简单连通性:无论何时使用DFS,都可以在线性时间内确定一个图是否连通4)顶点搜索:在给定顶点所在的同一个连通分量中有多

castle problem——(深度优先搜索,递归实现和stack实现)

将问题的各状态之间的转移关系描述为一个图,则深度优先搜索遍历整个图的框架为:Dfs(v) {if( v 访问过)return;将v标记为访问过;对和v相邻的每个点u: Dfs(u);}int main() {while(在图中能找到未访问过的点 k)Dfs(k);} 4例题:百练2815 城堡问题? 右图是一个城堡的地形图.请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大.城堡被分割成m×n(m≤50,n≤50)个方块,每个方块可以有0~4面墙.5输入输出? 输入? 程序从标准输入设备

深度优先搜索检测有向图有无环路算法

给定有向图 G = (V, E),需要判断该图中是否存在环路(Cycle).例如,下面的图 G 中包含 4 个顶点和 6 条边. 实际上,上图中存在 3 个环路:0->2->0, 0->1->2->0, 3->3. 深度优先搜索(DFS:Depth-First Search)可以用于检测图中是否存在环.DFS 会对一个连通的图构造一颗树,如果在构造树的过程中出现反向边(Back Edge),则认为图中存在环路. 对于非连通图,可以对图中的不同部分分别进行 DFS 构造树

sicily 1024 邻接矩阵与深度优先搜索解题

Description There are N cities and N-1 roads in Magic-Island. You can go from one city to any other. One road only connects two cities. One day, The king of magic-island want to visit the island from the capital. No road is visited twice. Do you know

一个例子,关于航班线路的深度优先搜索

1 java 代码,摘自<java 编程艺术> 2 3 /** 4 * 航班信息类 5 * 用于存放航班线路 6 * @author shiyan 7 * 8 */ 9 public class FlightInfo { 10 String from;//出发城市 11 String to;//目的城市 12 int distance;//距离 13 boolean skip;//回退标志 14 public FlightInfo(String f,String t,int d){ 15 th

&quot;《算法导论》之‘图’&quot;:深度优先搜索、宽度优先搜索及连通分量

本文兼参考自<算法导论>及<算法>. 以前一直不能够理解深度优先搜索和广度优先搜索,总是很怕去碰它们,但经过阅读上边提到的两本书,豁然开朗,马上就能理解得更进一步.  1. 深度优先搜索  1.1 迷宫搜索 在<算法>这本书中,作者写了很好的一个故事.这个故事让我马上理解了深度优先搜索的思想. 如下图1-1所示,如何在这个迷宫中找到出路呢?方法见图1-2. 图1-1 等价的迷宫模型 探索迷宫而不迷路的一种古老办法(至少可以追溯到忒修斯和米诺陶的传说)叫做Tremaux搜