图的深度搜索

终于进行到这一阶段了!

对于图问题,标准的解法是 标记数组加 dfs, 考查的抽象能力:情景问题转换为图的搜索问题。

第一个简单的问题:岛屿问题

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void dfs(vector < vector<int> >&mark ,vector < vector<int> >& ver, int x, int y ,int &M)
{
    mark[x][y] = 1;
    static const int dx[] = {-1 ,1 , 0 ,0};
    static const int dy[] = {0 ,0 , -1 ,1};
    for(int i=0; i<4 ;++i)
    {
    int newx = dx[i] +x;
    int newy = dy[i] +y;
    if( newx<0 || newx >= mark.size()|| newy <0 || newy >=mark[newx].size())
    {
        continue;
    }
    if( mark[newx][newy]==0 && ver[newx][newy] == 1)
    {
        dfs(mark,ver,newx,newy,M);
    }
}
}

int main()
{
    int M;
    vector < vector<int> > ver;
    cin >> M;
    int num = 0;
    vector  < vector<int> > mark(M ,vector<int>(M,0));
    //处理输入
   for(int i=0; i< M;++i)
    {    vector<int> tmp;
         int  tmpm;
        for(int j=0; j<M; ++j )
        {
            cin >> tmpm;
            tmp.push_back(tmpm);
        }
         ver.push_back(tmp);
         tmp.clear();
    }
    
    for (int i=0 ;i<M ;++i)
        for(int j=0;j<M;++j)
        {
            if(mark[i][j]==0 && ver[i][j]==1)
               { 
                  dfs(mark,ver,i,j,M);
                  cout << i <<j << endl ;
                 num ++;
               }
        }
    cout << num  << endl;
    /*
    for (int i=0;i<ver.size();++i)
      for(int j=0;j<ver.size();++j)
      cout << ver[i][j] << endl;*/
}

这个题最简单的搜索问题,对图遍历了一遍,标记数组没有更新。

同学的一个python的写法,总感觉不对,没加标记数组,边界条件也判断不清楚!代码的参考点在处理输入上!

class Solution:
    def IslandsNums(self, grid):
        if len(grid) == 0 or grid is None:
            return 0
        m = len(grid)
        n = len(grid[0])
        count = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    self.dfs_find(grid, i, j, m, n)
                    count += 1
        return count
        
    def dfs_find(self, grid, i ,j, m, n):
        if  grid[i][j] == 1:
            grid[i][j] = 0
            if (i-1 >= 0 and grid[i-1][j] == 1):
                self.dfs_find(grid, i-1, j, m, n)
            if (i+1 < m and grid[i+1][j] == 1):
                self.dfs_find(grid, i+1, j, m, n)
            if (j-1 >= 0 and grid[i][j-1]==1):
                self.dfs_find(grid, i, j-1, m, n)
            if (j+1 < n  and grid[i][j+1]==1):
                self.dfs_find(grid, i, j+1, m, n)
        return
M = int(input())
matrix = []
for i in range(M):
    matrix.append(list(map(int, input().split(' '))))
   
print(Solution().IslandsNums(matrix))

第二个问题:词语阶梯

图的表示与构造:邻接表

   构造成队列的形式是方便向搜索队列中添加。

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>

using namespace std;

bool conncet(const string word1,const string word2)
{
    int cnt = 0;
    for(int i=0 ;i<word1.length();++i)
    {
        if(word1[i]!= word2[i])
        {
            cnt ++;
        }
    }
    return cnt == 1;
}
//构造邻接表
void construct_graph(string &beginWord, vector<string> &wordList,
     map<string ,vector<string> > &graph)
     {
         wordList.push_back(beginWord);
         for(int i=0;i<wordList.size();++i)
         graph[wordList[i]] = vector<string>();
     
     for(int i=0 ; i<wordList.size();++i)
     for(int j =i+1 ;j<wordList.size() ;++j)
     if(conncet(wordList[i],wordList[j]))
     {
         graph[wordList[i]].push_back(wordList[j]);
         graph[wordList[j]].push_back(wordList[i]);
     }
         
     }
int BFS( string &beginWord,string &endWord,map<string,vector<string> >&graph)
    {
        queue<pair<string,int> >Q; //搜索队列<顶点,步数>
        set<string> visit; //记录访问过的顶点
        Q.push(make_pair(beginWord,1));//添加起始点,起始点步数为1
        visit.insert(beginWord); //标记起点已经访问过
        while(!Q.empty())
        {
            string node = Q.front().first;
            int step = Q.front().second;
            Q.pop();//弹出节点
            if(node == endWord)
            return step;
            //取node的全部临时节点放入队列
            const vector<string> &neighbors = graph[node];
            for(int i=0;i<neighbors.size();++i)
            {
                if(visit.find(neighbors[i]) == visit.end())
                {
                    Q.push(make_pair(neighbors[i],step+1));
                    visit.insert(neighbors[i]);
                }
            }
        }
        return 0;
    }
class Solution
{
public:
    int getlenth(string beginWord,string endWord,vector<string>& wordList)
    {
        map<string,vector<string> >graph;
        construct_graph(beginWord,wordList,graph);
        return BFS(beginWord,endWord,graph);
    }
};
int main()
{
    string beginWord ="hit" ;
    string endWord = "cog" ;
    vector<string> wordList;
    wordList.push_back("hot");
    wordList.push_back("dot");
    wordList.push_back("dog") ;
    wordList.push_back("lot");
    wordList.push_back("log");
    wordList.push_back("cog");
    Solution solve;
    int result = solve.getlenth(beginWord,endWord,wordList);
    cout <<result;
    return 0;
}

第三个问题:

这个问题可以转换为一个有向联通图的搜索问题:即一个节点的关注度c =其它所有节点到本节点的所有路径和

然后对N个节点都进行这样的操作!这个题目还是很有难度的。

一:处理输入,保存成有向连通图

int main()
{
	int N = 0;
	cin >> N;
	int M = 0;
	cin >> M;
	vector<int>p;
	for (int i = 0; i<2 * M; ++i)
	{
		int t = 0;
		cin >> t;
		p.push_back(t);
	}
	vector<vector<int>>r(N, vector<int>(N, 0));
	for (int i = 2; i<=2 * M; i += 2)
	{
		r[p[i - 1] - 1][p[i - 2] - 1] = 1;
	}
	Solution s;
	cout << s.findCircleNum(r) << endl;
	//system("PAUSE");
	return 0;
}

第二部:设计算法

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值