【Ybt OJ】[基础算法 第4章]深度搜索

「 「 基础算法 」 」 4 4 4章 深度搜索
目录:

A.拔河比赛
B.数独游戏
C.虫食算

A . A. A. 例题 1 1 1 拔河比赛

在这里插入图片描述

分析:

对于每个人 只需要看这个人加在一队好还是二队
所以直接就行啦 ( ? (? (? ? ? ? ? ) ?) ?)
然后取 m i n min min即可.

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//#pragma GCC optimize(2)
#define reg register 
using namespace std;
typedef long long ll;
typedef double db;
int T,n,a[100005],ans;
inline void dfs(int dep,int num1,int que1,int num2,int que2)  //dfs
{
    
    
	if(dep>n)
	{
    
    
		if(abs(num1-num2)<=1)  //条件
			ans=min(ans,abs(que1-que2));  //取最小
		return;
	}
	dfs(dep+1,num1+1,que1+a[dep],num2,que2);  //分别加入一队
	dfs(dep+1,num1,que1,num2+1,que2+a[dep]);  //二队
}
int main(){
    
    
	scanf("%d",&T);
	while(T--)
	{
    
    
		scanf("%d",&n);
		for(reg int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		ans=1e8;
		dfs(1,0,0,0,0);
		printf("%d\n",ans);
	}
	return 0;
} 

B . B. B. 例题 2 2 2 数独游戏

洛谷 l i n k link link
在这里插入图片描述

分析:

用三个数组 分别存储:行 列 九宫格当前格子数字状态
然后模拟 1 1 1~ 9 9 9数字填写 即可.
洛谷上改改输入即可.

具体填数字: d f s dfs dfs解决

在这里插入图片描述
9 ∗ 9 9*9 99大矩阵分成 9 9 9 3 ∗ 3 3*3 33小矩阵来填

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#pragma GCC optimize(2)
#define reg register 
using namespace std;
typedef long long ll;
typedef double db;
string s;
const int N=15;
int a[N][N],x[N][N],y[N][N],f[5][5][N],out;
void pre()
{
    
    
	out=0;
	memset(x,0,sizeof(x));
	memset(y,0,sizeof(y));
	memset(f,0,sizeof(f));
}
int val(int x)
{
    
    
	if(x<4) return 1;
	if(x<7) return 2;  //分成小矩阵
	return 3;
}
bool check(int q,int b,int c)
{
    
    
	if(!x[q][c]&&!y[b][c]&&!f[val(q)][val(b)][c]&&a[q][b]==0) return 1;
	else return 0;
}
void dfs(int xx,int yy)  //模拟填数字
{
    
    
	if(out) return;
	if(xx>9)
	{
    
    
		for(reg int i=1;i<=9;i++)
			for(reg int j=1;j<=9;j++)
				printf("%d",a[i][j]);
		printf("\n");
		out=1; return;
	} 
	if(a[xx][yy]) 
	{
    
    
		if(yy==9) dfs(xx+1,1);
		else dfs(xx,yy+1);
	}
	for(reg int i=1;i<=9;i++)
	{
    
    
		if(check(xx,yy,i))
		{
    
    
			a[xx][yy]=i;
			x[xx][i]=y[yy][i]=f[val(xx)][val(yy)][i]=1;  //标记
			if(yy==9) dfs(xx+1,1);
			else dfs(xx,yy+1);
			a[xx][yy]=0;
			x[xx][i]=y[yy][i]=f[val(xx)][val(yy)][i]=0;
		}
	}
}
int main(){
    
    
	while(cin>>s)
	{
    
    
		if(s=="end ") return 0;
		pre();
		for(reg int i=1;i<=9;i++)
			for(reg int j=1;j<=9;j++)
			{
    
    
				if(s[(i-1)*9+j-1]!='.')
				{
    
    
					a[i][j]=s[(i-1)*9+j-1]-'0';  //转换数字
					x[i][a[i][j]]=1;
					y[j][a[i][j]]=1;
					f[val(i)][val(j)][a[i][j]]=1;
				}else a[i][j]=0;
			}
		dfs(1,1);	
	}
	return 0;
} 

C . C. C. 例题 3 3 3 虫食算

洛谷 l i n k link link
在这里插入图片描述
在这里插入图片描述

分析:

考虑从低位到高位不断填已经确定的数
但是不能把不确定的数都试一遍 会超时
那么我们每确定一个数 就把已知式子未知进位的式子试一遍
如果当前这一列三个值都试过 就加法进位
否则 如果没进位 ( a + b ) (a+b) (a+b)最低位是否 = c =c =c 有进位就看 ( a + b + 1 ) (a+b+1) (a+b+1)最低位是否 = c =c =c
最后一直 d f s dfs dfs就可以了.

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//#pragma GCC optimize(2)
#define reg register 
using namespace std;
typedef long long ll;
typedef double db;
const int N=35;
string s[4];
int n,ans[N],turn[N],num;
bool vis[N],ok;
inline void print()
{
    
    
	for(int i=1;i<=n;i++)
		printf("%d ",ans[i]);
	ok=1;
	exit(0);
}
inline bool check()
{
    
    
	int add=0;
	for(reg int i=n;i>0;i--)
	{
    
    
		int a=ans[s[1][i-1]-'A'+1],b=ans[s[2][i-1]-'A'+1],c=ans[s[3][i-1]-'A'+1];
		if(a!=-1&&b!=-1&&c!=-1)
		{
    
    
			if(add!=-1)  //没进位
			{
    
    
				if((a+b+add)%n!=c) return false;  //判断不合法
				if(i==1&&(a+b+add)/n) return false;
				add=(a+b+add)/n;  //赋值进位
			}else
			{
    
    
				if((a+b)%n!=c&&(a+b+1)%n!=c) return false;  //有进位情况
				if(i==1&&(a+b)/n) return false;
			}
		} else add=-1;
	}
	return true;
}
inline void dfs(int x)
{
    
    
	if(ok) return;
	if(x>n) print();
	for(reg int i=0;i<n;i++)
	{
    
    
		if(!vis[i])
		{
    
    
			vis[i]=1;
			ans[turn[x]]=i;
			if(check()) dfs(x+1);  //dfs填数
			vis[i]=0;
			ans[turn[x]]=-1;
		}
	}
}
int main(){
    
    
	scanf("%d",&n);
	cin>>s[1]>>s[2]>>s[3];
	for(reg int i=n-1;i>=0;i--)
		for(reg int j=1;j<=3;j++)
			if(!vis[s[j][i]-'A'+1])
			{
    
    
				vis[s[j][i]-'A'+1]=1;
				turn[++num]=s[j][i]-'A'+1;  //转化
			}
	memset(vis,0,sizeof(vis));
	memset(ans,-1,sizeof(ans));
	dfs(1);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/112337572
今日推荐