顺序题表之外的搜素2

P1706
啊先来夸一夸next_permutation

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
  int a[10];
  int n;
  cin >> n;
  for(int i = 1;  i<= n; i++) {
  	a[i] = i;
  }
  do {
  	for(int i = 1; i <= n; i++) {
  	cout << "    " <<a[i];
  }
  	cout << endl; 
  }while(next_permutation(a + 1, a + n + 1));
  return 0;
}

然后就用递归来做吧,就是在里面放一个for循环,然后每一次要标注,要还回去,记录的东西是搜索的数量,为了打印还要保存在数组里面,用的也是搜索的数量来标志数组

#include<bits/stdc++.h>
using namespace std;
int n,pd[100],used[100];//pd是判断是否用过这个数
void print()//输出函数
{
    int i;
    for(i=1;i<=n;i++)
    printf("%5d",used[i]);//保留五位常宽
    cout<<endl;
}
void dfs(int k)//深搜函数,当前是第k格
{
    int i;
    if(k==n) //填满了的时候
    {
        print();//输出当前解
        return;
    }
    for(i=1;i<=n;i++)//1-n循环填数
    {
        if(!pd[i])//如果当前数没有用过
        {
            pd[i]=1;//标记一下
            used[k+1]=i;//把这个数填入数组
            dfs(k+1);//填下一个
            pd[i]=0;//回溯
        }
    }
}
int main()
{
    cin>>n;
    dfs(0);//注意,这里是从第0格开始的!
    return 0;
}

P1219
哟西,八皇后问题
主要是如何标记不能再放的点,左边倾斜的对角线是它的横纵坐标和是相同的,向右边倾泄的是相减相同,用这个特点可以确定每一行不能放的列数,然后就用递归,放在哪些可以放的,dfs的参数还是递归了几次,每一次是循环每一列,满足三个条件,然后注意为了不越界,所以右斜就全部+n
每个不同的x对应不同的i,但是是有关系的

#include<iostream>
using namespace std;
int n,cnt;
bool lie[20];//列 
bool u[20];//左上到右下 
bool v[40];//右上到左下 
int a[20];
void pr()
{
	if(cnt<=3)
{
	for(int i=1;i<=n;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;
}	
 } 
void dst(int x)
{
	if(x>n)
	{
		cnt++;
		pr();
		return;
	}
	for(int i=1;i<=n;i++)
	{
		if(!lie[i]&&!u[x-i+n]&&!v[x+i])
		{
			lie[i]=1;
			u[x-i+n]=1;
			v[x+i]=1;
			a[x]=i;
			dst(x+1);
			lie[i]=0;
			u[x-i+n]=0;
			v[x+i]=0;
			
		}
	}
}
int main()
{

	cin>>n;
	dst(1);
	cout<<cnt;
	
 } 

P1605
这个就是很没有意思的广搜啦
看一下模板,循环多少种走法,然后得出出来可能的下一步,判断可以不可以走(越界||数据不对||不可以||走过来||,然后打上标记,继续深搜它,最后搜到结果就++

#include<iostream>
using namespace std;
int xx[]={-1,0,1,0};
int yy[]={0,1,0,-1};
bool mp[100][100]={0}; 
bool qia[100][100]={0};

int c,k,za,qix,qiy,zhx,zhy,a,cnt=0,b,dx,dy,x,y;
void dfs(int x,int y)
{
	if(x==zhx&&y==zhy)
	{
		cnt++;
		return;
	}
		for(int i=0;i<4;i++)
	{
		int dx=x+xx[i];
		int dy=y+yy[i];
		if(!mp[dx][dy]&&dx<=c&&dx>=1&&dy<=k&&dy>=1&&!qia[dx][dy])
		{
			mp[dx][dy]=1;
			dfs(dx,dy);
			mp[dx][dy]=0;
			
		}
	}
}
int main()
{

	cin>>c>>k>>za; 
	cin>>qix>>qiy>>zhx>>zhy;
	for(int i=1;i<=za;i++)
	{
		cin>>a>>b;
		qia[a][b]=1;
	}
	mp[qix][qiy]=1;
	dfs(qix,qiy);
	cout<<cnt;
}
	

P1101
这其实就是八个方向,连续的,先找到头,然后八个方向连续的都要满足,所以需要两重循环,一重确定方向,一重高歌猛进

#include<iostream>
using namespace std;
int m;
int p=1,flag;
char a[1100][1100];
int xx[]={-1,-1,-1,0,0,1,1,1};
int yy[]={-1,0,1,1,-1,1,0,-1};
int vis[1100][1100]={0}; 
string yz="yizhong";
void dfs(int x,int y)
{
	for(int i=0;i<8;i++)
	{	int flag=1;
		for(int j=0;j<7;j++)
		{
		int	dx=x+xx[i]*j;
		int	dy=y+yy[i]*j;
		if(yz[j]!=a[dx][dy]||!(dx>=1&&dx<=m&&dy>=1&&dy<=m))
			{flag=0;
			break;
			}
		}
        	if(flag)
		{
			for(int j=0;j<7;j++)
			{
		    int	dx=x+xx[i]*j;
		    int dy=y+yy[i]*j;
			vis[dx][dy]=1;
			}
		}
	}
}
int main()
{
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
			
		}
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(a[i][j]=='y')
			dfs(i,j);
		}
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(!vis[i][j])
			cout<<"*";
			else
			cout<<a[i][j];
		}
		cout<<endl;
	}
	
	return 0;
}

P1019
你需要他更加的长,所以是从最后一个来对照,然后向前走,每一个只能出现两遍

首先遍历所有的,找合适的头,找到深搜,记得还原
深搜内部要记录最长的答案
然后开始循环,记录两者的长度,while循环
然后用一个神奇的s.substr(la-p)==a[i].substr(0,p)

形式 : s.substr(pos, len)
返回值: string,包含s中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,即不加参数会默认拷贝整个s)

下一步深搜的长度是l+lb-p,两个人合起来减去重复的

#include<iostream>
#include<string.h> 
#include<algorithm>
using namespace std;
int vis[22];
int ans,m,p;
	string a[100];
	char c; 
void dst(string s,int l)
{
	ans=max(ans,l);
	for(int i=1;i<=m;i++)
	{
		int p=1;
		int la=s.length();
		int lb=a[i].length();
		while(p<min(la,lb))
		{
		if(s.substr(la-p)==a[i].substr(0,p)&&vis[i]<2 )
		{
			vis[i]++;
			dst(a[i],lb+l-p);
			vis[i]--;
			break;
		}
		p++;
		}
		
	}
}
int main()
{
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>a[i];
	}
	cin>>c;
	for(int i=1;i<=m;i++)
	{
		if(a[i][0]==c)
		{
			vis[i]++;
			dst(a[i],a[i].length());
			vis[i]--;
		}
	}
	cout<<ans;
 } 

听刘露阳的话,好好学基础

  #include<cstdio>
  #include<iostream>
  #include<string>
  using namespace std;
  struct word{
      string line;
      int left=2; 
  }w[25];
  int n,maxA;
  inline int find(int last,int next)
  {
      int lenl=w[last].line.length(),lenn=w[next].line.length();
      for(int i=lenl-1;i>=1;--i)
      {
          if(w[last].line[i]==w[next].line[0])
          {
              int k=i,j=0,cl=0;
              while(j<lenn && k<lenl)
              {
                  if(w[last].line[k]==w[next].line[j])++cl;
                  else return 0;
                  ++k;++j;
              }
              if(k==lenl && j<lenn)return cl;
              else return 0;
          }
      }
      return 0;
  }
  inline void dfs(int now,int length)
  {
      bool flag=false;//所谓的标志变量 
      for(int i=1;i<=n;i++)
      {
          if(!w[i].left)continue;//一个单词只能用两次; 
          else
          {
              int x=find(now,i);
              if(x)
              {
                  flag=true;//搜到变成真 
                  --w[i].left;
                  length+=(w[i].line.length()-x);
                  dfs(i,length);
                  ++w[i].left;
                  length-=(w[i].line.length()-x);
                  //这边不仅编号要回溯,长度也要回溯(卡了我很久)
                  //至于为什么,就是因为dfs结束,返回到了这里,那么dfs这一趟完了,这个长度和次数还要用到下一次搜索当中去。 
              }
              else flag=false;//标志变量为假就是搜完了,没有可连接单词; 
          }
      }
      if(!flag) maxA=max(maxA,length);

  }
  int main()
  {
      scanf("%d",&n);
      //for(int i=1;i<=n;i++)w[i].left=2;
      for(int i=1;i<=n;i++)cin>>w[i].line; 
      char p=getchar();cin>>p;
      //输入完成; 
      for(int i=1;i<=n;i++)
      {
          if(w[i].line[0]==p)
          {
              --w[i].left;
              dfs(i,w[i].line.length());
              ++w[i].left;
              //这边也要回溯,同上。 
          }
      }
      printf("%d",maxA);//最后输出最大值; 
      return 0;
  }

P1162
比和空间:绝对不是循环www,可以在外面套一层0,然后就把他围起来了,然后把这些0都标志上,那么没标志的0,就是要变成2的了

使用广搜,上下左右

#include<iostream>
#include<queue>
using namespace std;
queue <int> x;
queue <int> y;
int xx[]={1,0,-1,0};
int yy[]={0,-1,0,1};
int vis[31][31]={0};
int a[31][31];
int m,dx,dy;
int main()
{
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
		}
	 } 
	 x.push(0);
	 y.push(0);
	 a[0][0]=0;
	 while(!x.empty() )
	 {
	 	for(int i=0;i<4;i++)
	 	{
	 	 dx=x.front() +xx[i];
	 	 dy=y.front() +yy[i];
	 	 if(dx>=0&&dx<=m+1&&dy>=0&&dy<=m+1&&a[dx][dy]==a[x.front() ][y.front() ]&&!vis[dx][dy])
	 	 {
	 	 	x.push(dx);
	 	 	y.push(dy);
	 	 	vis[dx][dy]=1;
		  }
		 }
		 x.pop() ;
		 y.pop() ; 
		 
	   
	 }
	 	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
		     if(a[i][j]==0&&vis[i][j]==0)
		     {
		     	a[i][j]=2;
			 }
			 cout<<a[i][j]<<" ";
		}
		cout<<endl;
	 } 
	 
	
}

P1443
走到棋盘上任意一点,进行广搜

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int xx[]={-2,-2,-1,-1,1,1,2,2};
int yy[]={1,-1,2,-2,2,-2,1,-1};
struct Node
{
	int x;
	int y;
	int t;
}; 
queue <Node> Q;
int n,m,qi,zh,dx,dy;
int vis[401][401];

int main()
{
	cin>>n>>m;
	cin>>qi>>zh;
	Q.push((Node){qi,zh,0});
	memset(vis,-1,sizeof(vis));
	vis[qi][zh]=0;
	while(!Q.empty() )
	{
	
		for(int i=0;i<=7;i++)
		{
		 int dx=xx[i]+Q.front().x;
		 int dy=yy[i]+Q.front().y;
		 if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&vis[dx][dy]==-1)	
		 {
		 	vis[dx][dy]=Q.front().t+1;
		 	Q.push((Node){dx,dy,Q.front().t+1});
		 }
		}
		Q.pop();
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			printf("%-5d ",vis[i][j]) ;
		}
		cout<<endl;
	}
	return 0;
 } 

P1141
询问可以到那个格子,那么意味着这一片地方都是一个值,然后是否访问可以直接计成colour,来区分不同的colour走的cnt,cnt++一定要放在最后,以出队的个数为准,然后把coulour放到ans里面,cnt就是它的值,coulour,就是visit[x][y]

#include<iostream>
#include<queue> 
using namespace std;
int xx[]={1,0,-1,0};
int yy[]={0,1,0,-1};

int vis[1001][1001]={0},colour=0,dx,dy,m,cnt,n;
int ans[1000];
int mp[1001][1001]={0};
void bst(int i,int j)
{
    queue<int>x;
    queue<int>y;
	x.push(i);
	y.push(j);
	vis[i ][j ]=colour;
	while(!x.empty())
	{   
		for(int i=0;i<=3;i++)
		{
			dx=x.front() +xx[i];
			dy=y.front() +yy[i];
			if(dx>=1&&dx<=m&&dy>=1&&dy<=m&&!vis[dx][dy]&&mp[dx][dy]!=mp[x.front()][y.front()])
			{
				vis[dx][dy]=colour;
				x.push(dx);
				y.push(dy);
				
			}
		}
			x.pop() ;
		    y.pop() ;
    	cnt++;///cnt的位置 
		}	
}
int main()
{
	char c;
	cin>>m>>n;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>c;
			if(c=='1')
			mp[i][j]=1;
			if(c=='0')
			mp[i][j]=0; 
		}
	 } 
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		if(!vis[i][j])
		{
			++colour;
			bst(i,j);
			ans[colour]=cnt;
			cnt=0;
		}
	
		
	}
	for(int i=1;i<=n;i++)
	{
		int hx,hy;
	   cin>>hx>>hy;
	   cout<<ans[vis[hx][hy]]<<endl;
	}
	
}

P1604
来看看进制转化的实质,应该是不需要十进制作为中间商了
前面就都当做正常的高精度计算(毕竟你需要把ABCD转化)
然后直到相加得到c,c得到之后要进位,进位的时候整除和取余要用到c

#include<iostream>
#include<algorithm>
#include<cstring> 
#include<math.h>
using namespace std;
string s1,s2;
int a[100089],b[100089],la,lb,lc,c[100032];
int main()
{
	int n;
	cin>>n;
	
	cin>>s1>>s2;
	la=s1.length() ;
	lb=s2.length() ;
	for(int i=0;i<la;i++)
	{
		if(s1[i]<='9')
		{
		a[la-i]=s1[i]-'0';
		}
		else
		{
			a[la-i]=s1[i]-'A'+10;
		}
		
	}
	for(int i=0;i<lb;i++)
	{
	if(s2[i]<='9')
		{
		b[lb-i]=s2[i]-'0';
		}
		else
		{
			b[lb-i]=s2[i]-'A'+10;
		}
	}
     lc=max(la,lb)+1;
     for(int i=1;i<=lc;i++)
     {
     	c[i]+=a[i]+b[i];
     	c[i+1]+=c[i]/n;
     	c[i]%=n;
	 }
	 while(c[lc]==0&&lc>1)
	 lc--;
	 
	 for(int i=lc;i>=1;i--)
	 {
	 	if(c[i]>=10)
	 	cout<<char(c[i]-10+'A');
	 	else
	 	cout<<c[i];
	 }
     
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值