Search Algorithm introduction

search algorithm

Since in the assignment 7, we have a search problem which is a sudoku, I decided to write something about search algorithm.

1.Summary

When it comes to search algorithm, everyone would think about DFS(depth first search) and BFS(breadth first search).The difference between them is that DFS is a way to search to the bottom and then back search for another path, but when we use BFS, the first solution we find is the shortest path.Now,let’s go deeper to these problems.

2.DFS

When we use DFS,there is a fixed pattern:search,suppose,recall.something like this way:

for(int i=0;i<n;i++)      //search
{
  if(blablabla)
  {
    graph[i]=i;      //suppose
    dfs();
    graph[i]=0;       //recall
  }
}  

Now,let try a simple problem:

four-color problems(code_vss P1116)

DESCRIPTION:
给定N(小于等于8)个点的地图,以及地图上各点的相邻关系,请输出用4种颜色将地图涂色的所有方案数(要求相邻两点不能涂成相同的颜色)
数据中0代表不相邻,1代表相邻
INPUT DISCRIPTION:
第一行一个整数n,代表地图上有n个点
接下来n行,每行n个整数,每个整数是0或者1。第i行第j列的值代表了第i个点和第j个点之间是相邻的还是不相邻,相邻就是1,不相邻就是0.
我们保证a[i][j] = a[j][i] (a[i,j] = a[j,i])
OUTPUT DISCRIPTION:
染色方案数

SAMPLE INPUT
8
0 0 0 1 0 0 1 0
0 0 0 0 0 1 0 1
0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
1 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0
SAMPLE OUTPUT
15552

SOLUTION
This isn’t a complicated problem.So you can simply understand when you read the code blow:

#include<iostream>
using namespace std;
bool map[10][10]={0};
int color[10]={0};
int count=0;
int n;
/* check whether the color has been used for the former one */
bool check(int index,int num)  
{
    for(int i=1;i<num;i++)
    {
        if(map[num][i])
        {
            if(color[i]==index)
            {
                return false;
            }
        }
    }
    return true;
}
/* the main process --recursion */
void dfs(int num)
{
    if(num==n+1)
    {
        count++;
        return;
    }
    for(int i=1;i<=4;i++)
    {
        if(check(i,num))
        {
            color[num]=i;
            dfs(num+1);
            color[num]=0;
        }
    }
    return;
}
int main(void)
{
    //int n=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>map[i][j];
        }
    }
    dfs(1);
    cout<<count<<endl;
} 

3.BFS

As the passage says above, BFS can find the shortest path easily(which means you don’t need to compare which is the shortest manually).The realization of BFS need to use queue.First,find the first tier and push them into the queue.Then,pick out the first one,find the nodes linked with this node and put them into the queue.Finally finish your search when you find you reach the final location.For details,you can see this(this blog explain the problems with picturesm,which is quite suitable for those who just started to learn bfs)


maze problem(poj 3849)

DESCRIPTION
定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示:

int maze[5][5] = {          
      0, 1, 0, 0, 0,   
      0, 1, 0, 1, 0,   
      0, 0, 0, 0, 0,  
      0, 1, 1, 1, 0,  
      0, 0, 0, 1, 0  };  

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],既第一空格是可以走的路。Input一个N × M的二维数组,表示一个迷宫。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道
Output
左上角到右下角的最短路径

Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
My solution

#include<iostream>
#include<vector>
#include<cstdlib>
using namespace std;
int dx[4] = { 0,-1,1,0 };
int dy[4] = { 1,0,0,-1 };
typedef struct unit {
    int x;
    int y;
    int pre;
}unit;
vector<unit>Data;
int answer[30];
int map[5][5];
void init()
{
    for (int i = 0;i<5;i++) {
        for (int j = 0;j<5;j++) {
            cin >> map[i][j];
        }
    }
}
void print(int num)
{
    int count = 0;
    unit* index = &Data[num];
    do {
        answer[count] = index->x;
        answer[count + 1] = index->y;
        count += 2;
        if (index->pre == -1) {
            break;
        }
        else {
            index = &Data[index->pre];
        }
    } while (1);
    for (int i = count - 2;i >= 0;i -= 2)
    {
        cout << '(' << answer[i] << ", " << answer[i + 1] << ')' << endl;
    }
    cout << "(4, 4)" << endl;
}

void bfs()
{
    unit* p0 = new unit;
    p0->pre = -1;
    p0->x = 0;
    p0->y = 0;
    Data.push_back(*p0);
    map[0][0] = 1;

    int currX = 0, currY = 0, x, y, now = 0, last = 1;
    do {
        currX = Data[now].x;
        currY = Data[now].y;
        for (int i = 0;i<4;i++) {
            x = currX + dx[i];
            y = currY + dy[i];
            if (x == 4 && y == 4) {
                print(now);
                exit(0);        //find the path
            }
            if (x <= 4 && x >= 0 && y <= 4 && y >= 0) {
                if (map[x][y] != 1) {
                    unit* index = new unit;
                    index->pre = now;
                    index->x = x;
                    index->y = y;
                    map[x][y] = 1;
                    Data.push_back(*index);
                    last++;
                }
            }
        }
        now++;
    } while (now!=last);
}
int main(void)
{
    init();
    bfs();
    return 0;
}

4.Final

Since I am a beginner in studying Search algorithm, I didn’t have to much thinking about this.But finally,I’d like to give you some oj problems and my own solutions you can refer to.
Superprime(vijos P1359)
my code:

#include<iostream>
using namespace std;
int n=0,num=0;
bool check(int num)
{
    if(num==1)
    return false;
    for(int i=2;i*i<=num;i++)
    {
        if(num%i==0)
        {
            return false;
        }
    }
    return true;
}
void dfs(int pos)
{
    if(pos==n+1)
    {
        cout<<num<<endl;
        return;
    }
    for(int i=1;i<=9;i++)
    {
        num=num*10+i;
        if(check(num))
        {
            //index*=10;
            //count++;
            dfs(pos+1);
            //index/=10;
        }
        num=(num-i)/10;
    }
}
int main(void)
{

    cin>>n;
    dfs(1);

} 

Sukodu(vijos Tongji2016c++ domain P4)
attention:if you search directly,you will probably out of time.So you need to pruning in some ways.
my code:

#include<iostream>
using namespace std;
int graph[9][9]={0};
//bool able[10]={0};
//can't use global variables for it may
//change the value when you search for the 
//next step,and when you return,the value in
//this global variable may not be the original one
//so the solution is to pass a local variable to 
//the `check` function 
int result=0,count=0;
int weight[9][9]=
{
    1,1,1,1,1,1,1,1,1,
    1,3,3,3,1,3,3,3,1,
    1,3,6,3,6,3,6,3,1,
    1,3,3,3,1,3,3,3,1,
    1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,
    1,1,1,9,1,9,1,1,1,
    1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,
};
void calculate()
{
    int index=0;
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
            index+=(weight[i][j]*graph[i][j]);
        }
    }
    if(index>result)
    {
        result=index;
    }
}
int check(int x,int y,bool able[10])
{
    for(int i=1;i<10;i++)
    {
        able[i]=true;
    }
    for(int i=0;i<9;i++)
    {
        able[graph[i][y]]=false;
        able[graph[x][i]]=false;
    }
    x=x/3*3;
    y=y/3*3;
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            able[graph[x+i][j+y]]=false;
        }
    }
    int a=0;
    for(int i=1;i<10;i++)
    {
        if(able[i])
        {
            a++;
        }
    }
    return a;
}
void dfs()
{
    bool able[10];
    int xx=-1,yy,index,min=10;
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
            if(graph[i][j]) continue;
            index=check(i,j,able);
            if(index==0)    return;
            if(index<min)
            {
                min=index;
                xx=i;
                yy=j;
            }
        }
    }
    if(xx==-1)
    {
        count++;
        calculate();
        //display();
        return;
    }
    check(xx,yy,able);
    for(int i=1;i<10;i++)
    {
        if(able[i])
        {
            graph[xx][yy]=i;
            dfs();
        }
    }
    graph[xx][yy]=0;
}
int main(void)
{
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
            cin>>graph[i][j];
        }
    }
    dfs();
    if(result)
    {
        cout<<result<<endl;
    }
    else 
    cout<<"-1"<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值