ACM学习笔记DAY4

ACM学习笔记DAY4

今天学习的主要内容为DFS
首先是DFS的基本模板

在这里插入图片描述
然后最经典的最基础的DFS的运用:全排列问题

#include<iostream>
using namespace std;
int a[100];
int b[100];
int n;
void dfs(int x)
{
	if (x == n + 1)
	{
		for (int i = 1; i <= n; i++)
		{
			cout << a[i] << " ";
		}
		cout << endl;
		return;
	}


	for (int i = 1; i <= n; i++)
	{
		if (b[i] == 0)
		{
			a[x] = i;
			b[i] = 1;
			dfs(x + 1);
			b[i] = 0;
		}
	}
	return;
}
int main() {
	cin >> n;
	dfs(1);
}

下面的是关于图的一些基础知识以及一个基础的DFS

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
接下来是在今天没有ac的题目
在这里插入图片描述
第一题:
在这里插入图片描述

#include<stdio.h>
#include<string.h>
int n,k;
int cnt,sum;
char map[10][10];
int vis[10];
void dfs(int s){
    if(cnt==k){
        sum++;
        return;
    }
    if(s>=n) return;
    for(int i=0;i<n;i++){
        if(map[s][i]=='#'&&!vis[i]){
            vis[i]=1;
            cnt++;
            dfs(s+1);
            cnt--;
            vis[i]=0;
        }
    }
    dfs(s+1);
}
int main(){
while(scanf("%d%d",&n,&k)&&n!=-1&&k!=-1){
    cnt=sum=0;
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++){
        scanf("%s",map[i]);
    }
    dfs(0);
    printf("%d\n",sum);
}
    return 0;
}

第二题:
在这里插入图片描述
在这里插入图片描述

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,t;
int ex,ey;
int s[10][10];
int vis[10][10];// 标记那些点不能走 
int nex[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; // 四个方向 
bool dfs(int x, int y, int tmp)
{
	if(tmp > t)return false;
	if(tmp != t && s[x][y] == 'D')return false;
	if(tmp == t && s[x][y]=='D')return true;
	if(tmp == t && s[x][y]!='D')return false; // 剪枝 
	int left = t - tmp; // 剩余的时间 
	int maxn = abs(ex-x) + abs(ey-y); // 剩余需要走的步数 
	if(left < maxn) return false; // 如果剩余的时间小于至少需要走的步数,那么剪枝 
	if(abs(maxn-left) %2 == 1)return false; // 根据奇偶行剪枝 
	for(int i=0; i<4; i++)
    {
	  int xx = x + nex[i][0];
	  int yy = y + nex[i][1];
	  if(xx>=1 &&xx<=m && yy>=1 && yy <=n && vis[xx][yy]==0 && s[xx][yy]!='X')
	  {
	    vis[xx][yy] = 1;
		if(dfs(xx,yy,tmp+1))return true;
		vis[xx][yy] = 0;// 回溯		
	  }
	}	
	return false;
}
int main()
{
	while(scanf("%d %d %d", &m,&n, &t)!= EOF)
	{
	   if(m+n+t==0)break;
	   memset(vis, 0, sizeof(vis));
	   int x,y;
	   for(int i=1; i<=m; i++)
	   {
	     for(int j=1; j<=n; j++)
		 {
		    scanf(" %c", &s[i][j]);
			if(s[i][j]=='S')
			{
			  x=i; y=j;	
			}
			if(s[i][j]=='D')
			{
				ex=i; ey=j;
			}		
		 }		
	   }
	    vis[x][y] = 1; // 起点只能走一次,所以以后是不可能走起点了 
		if(dfs(x,y,0))cout << "YES" << endl;
		else cout << "NO" << endl;	
	}
	return 0;
}

下面是最后一道题:
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include<cstdio>
#include <vector>
#include<limits.h>
using namespace std;
const int maxn = 105, INF = INT_MAX;
int K, N, R, visited[maxn] = { 0 };//钱币,城市,路线
int len = 0, minlen = INF, expense = 0;
int minvisited[maxn][10010];//表示到达节点v花费为cost的最短路径,用于剪枝
struct ROAD
{
    int e, l, t;//终点,长度,花费
}r;
vector<ROAD>G[maxn];//100个城市
void DFS(int v)//如果参数设置为点,那么要在DFS子节点的时候做判断
{
    if (v == N)//到达终点
    {
        if (len < minlen) minlen = len;//取最小值
        return;
    }
    for (int j = 0; j < G[v].size(); j++)//DFS所有子节点
    {
        if (!visited[G[v][j].e])//子节点没有被访问
        {
            int cost = G[v][j].t + expense, length = G[v][j].l + len;
            if (cost <= K && length < minlen && length < minvisited[G[v][j].e][cost])
            {//剪枝:不超过总费用,长度小于最小总长度,长度小于到达某个点费用为cost的最小长度,DFS
                visited[G[v][j].e] = 1;//标记为访问
                len += G[v][j].l;//深度加一
                expense += G[v][j].t;//钱币加上本条路径的费用
                minvisited[G[v][j].e][cost] = length;
                DFS(G[v][j].e);//DFS
                len -= G[v][j].l;//恢复原状态
                expense -= G[v][j].t;
                visited[G[v][j].e] = 0;//恢复原状态
            }
        }
    }
}
int main()
{
    for (int i = 0; i < maxn; i++)
    {
        for (int j = 0; j < 10010; j++) minvisited[i][j] = INF;
    }
    cin >> K >> N >> R;
    int s;
    for (int i = 1; i <= R; i++)
    {
        scanf("%d%d%d%d", &s, &r.e, &r.l, &r.t);
        G[s].push_back(r);
    }//构图
    visited[1] = 1;
    DFS(1);
    if (minlen != INF) cout << minlen << endl;
    else cout << -1 << endl;
    return 0;
}

-7.9 共勉

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值