算法合集3.13

bfs

#include<bits/stdc++.h>
using namespace std;
int a[100][100],v[100][100];
struct point{
	int x;
	int y;
	int step;
};
queue<point>r;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
int main(){
	int n,m,startx,starty,p,q;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
		}
	}
	scanf("%d%d%d%d",&startx,&starty,&p,&q);
	point start;
	start.x=startx;
	start.y=starty;
	start.step=0;
	r.push(start);
	v[startx][starty]=1;
	int flag=0;
while(!r.empty()){
int x=r.front().x,y=r.front().y;	
	if(x==p&&y==q){
	flag=1;
	printf("%d",r.front().step);
	break;	
	}
	for(int k=0;k<=3;k++){
		int tx,ty;
		tx=x+dx[k];
		ty=y+dy[k];
		if(a[tx][ty]==1&&v[tx][ty]==0){
			point temp;
			temp.x=tx;
			temp.y=ty;
			temp.step=r.front().step+1;
			r.push(temp);
			v[tx][ty]=1;
		}
	}
	r.pop();
}	
if(flag==0)	printf("no answer!");	
	return 0;
}

 dfs

#include<bits/stdc++.h>
using namespace std;
const int N=1e2+10;
int mp[N][N],vis[N][N];
bool fg=false;
int dx[4]={0,0,-1,1};
	int dy[4]={-1,1,0,0};
	int n;
	int sx,sy,ex,ey;
//	bool check(int nx,int ny){
//	if(nx>0&&nx<n&&ny>0&&ny<=n&&vis[nx][ny]!=false&&mp[nx][ny]==0){
//		return true;
//	}	
//	return false;
//	}
void dfs(int x,int y){
	if(vis[x][y]||fg)return;
	vis[x][y]=true;
	if(x==ex&&y==ey){
		fg=true;
		return;
	}
	for(int i=0;i<4;++i){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>0&&nx<=n&&ny>0&&ny<=n&&vis[nx][ny]==false&&mp[nx][ny]==0){
			dfs(nx,ny);
		}
	}
}
int main(){
	
	cin>>n;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			cin>>mp[i][j];
		}
	}
	cin>>sx>>sy>>ex>>ey;
	if(mp[sx][sy]==1){
		puts("NO");
		return 0;
	}
	dfs(sx,sy);
	puts(fg?"YES":"NO");
	return 0;
}

 并查集

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
 
using namespace std;
 
const int inf = 0x3f3f3f3f;
const int maxn = 10051005;
int m,n,k,pre[maxn],ans;
bool vis[maxn];
 
void init()
{
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n*m;i++)
		pre[i] = i;	
}
 
int find(int x)  
{
	if(x!=pre[x])
		return pre[x] = find(pre[x]);
	return x;
}
 
void join(int x,int y)
{
	int xx = find(x);
	int yy = find(y);
	if(xx!=yy)
	{
		pre[yy] = xx;
	}
}
 
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	init();
	for(int i=0;i<k;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		join(x,y);
	}
	for(int i=1;i<=n*m;i++)
	{
		vis[find(i)] = 1;
//		cout<<pre[i]<<" "<<find(i)<<endl;
	}
	for(int i=1;i<=n*m;i++)
		ans += vis[i];
	cout<<ans<<endl;
	return 0;
}

大数加法

7-5 a+b(正长小数版) (5 分)

给定两个正的小数a,b,求a,b之和。需要注意的是,这两个小数的有效数字位数比较多,最大有100位有效数字。

输入格式:

两行,分别表示正小数a,b。该小数一定带有小数点。

输出格式:

两者之和。如果结果小数存在末尾0,均保留。

输入样例:

0.9999999999999999999999999999999999999999999999999999999999
0.0000000000000000000000000000000000000000000000000000000001

输出样例:

1.0000000000000000000000000000000000000000000000000000000000

 

#include<stdio.h>
#include<string.h>
int search(char a[]){
	int i=0;
	while(a[i]!='.'){
		i++;
	}
		return i;
}
int main(){
	char a[220],b[220],m[220];
	int pa,pb,pc,stra,strb;
	int i,j,n;
	gets(a);
	gets(b);
	stra=strlen(a)-1;
	strb=strlen(b)-1;
	pa=search(a);
	pb=search(b);
	pc=pb;
	if(pa>=pb){strcpy(m,a);pc=pa;}
	else strcpy(m,b);
	int xiao=stra-pa,zeng=pa;
	if(pa>pb)zeng=pb;
	if(stra-pa>=strb-pb){
		xiao=strb-pb;
		for(n=stra-pa;n>0;n--){
			i=n+pc;
			j=n+pa;
			m[i]=a[j];
		}
	}
	else for(n=strb-pb;n>0;n--){
		i=n+pc;
		j=n+pb;
		m[i]=b[j];
	}
//	printf("xiao=%dpc=%d\n",xiao,pa);
	
	//¼Ó·¨
	int t=0;
	 for(;xiao>0;xiao--){
	 	i=pa+xiao;
	 	j=pb+xiao;
	 	n=pc+xiao;
	 	m[n]=a[i]+b[j]-'0'+t;
         t=0;
	 	if(m[n]>'9'){m[n]-=10;t=1;}
	 }
	 int k;
	 for(k=1;k<=zeng;k++){
	 	i=pa-k;
	 	j=pb-k;
	 	n=pc-k;
	 	m[n]=a[i]+b[j]-'0'+t;
         t=0;
		if(m[n]>'9'){m[n]-=10;t=1;}
         
	 }
	 if(t==1)for(--n;n>=0;n--){
	 	m[n]=m[n]+t;
	 	t=0;
	 	if(m[n]>'9'){m[n]-=10;t=1;}
	 }
	 if(t==1&&n==-1)printf("1");
	 puts(m);
}

 你终于回来了(。・∀・)ノ (cnblogs.com)

标题:机器人繁殖
X星系的机器人可以自动复制自己。它们用1年的时间可以复制出2个自己,然后就失去复制能力。
每年X星系都会选出1个新出生的机器人发往太空。也就是说,如果X星系原有机器人5个,
1年后总数是:5 + 9 = 14
2年后总数是:5 + 9 + 17 = 31
如果已经探测经过n年后的机器人总数s,你能算出最初有多少机器人吗?


数据格式:

输入一行两个数字n和s,用空格分开,含义如上。n不大于100,s位数不超过50位。
要求输出一行,一个整数,表示最初有机器人多少个。

例如:
用户输入:
2 31
则程序应该输出:
5
再例如:
用户输入:
97 2218388550399401452619230609499
则程序应该输出:
8
资源约定:
峰值内存消耗 < 512M
CPU消耗  < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

#include<iostream>
#include<cmath>
using namespace std;
int main(){
    //需要注意,这里可能会用到大数运算,但非常神奇的就是这里的double居然不会出错
    double s;
    int n, k;
    cin >> n >> s;
    k = (s-n-1)/(pow(2, n+1) -1) +1;
    cout << k;
    return 0;
}

 

从X星截获一份电码,是一些数字,如下:
13
1113
3113
132113
1113122113
....

YY博士经彻夜研究,发现了规律:
第一行的数字随便是什么,以后每一行都是对上一行“读出来”
比如第2行,是对第1行的描述,意思是:1个1,1个3,所以是:1113
第3行,意思是:3个1,1个3,所以是:3113

请你编写一个程序,可以从初始数字开始,连续进行这样的变换。

输入

第一行输入一个数字组成的串,不超过100位
第二行,一个数字n,表示需要你连续变换多少次,n不超过20

输出一个串,表示最后一次变换完的结果。

输出

输出一个串,表示最后一次变换完的结果。

 

样例输入

5
7

样例输出

13211321322115
#include<iostream>
#include<string.h>
#include<string>
using namespace std;

int main()
{
	char code[10000];
	memset(code, '\0', sizeof(code));       // 注意要初始化
	char codetmp[10000];
	memset(codetmp, '\0', sizeof(codetmp)); // 注意要初始化

	int index = 0;
	int n;
	cin >> code;
	int len = strlen(code);
	cin >> n;
	char start;
	int num = 0;
	while (n--)       // 这个while循环针对code数组
	{
		bool flag = 0;
		start = code[0];    // 标记当前连续的那个字符
		
		index = 0;   num = 0;
		len = strlen(code);

		for (int i = 0; i<len; i++)
		{
 			if (code[i]==start)    // 如果 当前字符==当前连续字符
				num++;
			if (i == len-1)        // 如果已经是最后一个字符了
				flag = 1;
			if (code[i]!=start)
			{
				/* 先把个数num和字符start存起来 */
				codetmp[index++] = num + '0';   // codetmp是字符数组,所以要加上'0'
				codetmp[index++] = start;
				/* 再把当前连续字符换成code[i] */
				start = code[i];
				num = 1;
			}
		}
		if (flag) // 如果已经是最后一个字符,因为我们还没有存num和start,得操作如下
		{
			codetmp[index++] = num + '0';
			codetmp[index++] = start;
		}
		
         /* 因为要保证while循环针对code数组,这里把codetmp数组复制到code数组 */
		int t_len = strlen(codetmp);
		for (int i = 0; i<t_len; i++)
			code[i] = codetmp[i];
	}
	cout << code << endl;
//	system("pause");
}

 

题目描述

X星的坦克战车很奇怪,它必须交替地穿越正能量辐射区和负能量辐射区才能保持正常运转,否则将报废。
某坦克需要从A区到B区去(A,B区本身是安全区,没有正能量或负能量特征),怎样走才能路径最短?

已知的地图是一个方阵,上面用字母标出了A,B区,其它区都标了正号或负号分别表示正负能量辐射区。
例如:
A + - + -
- + - - +
- + + + -
+ - + - +
B + - + -

坦克车只能水平或垂直方向上移动到相邻的区。

 

输入

输入第一行是一个整数n,表示方阵的大小, 4<=n<100
接下来是n行,每行有n个数据,可能是A,B,+,-中的某一个,中间用空格分开。
A,B都只出现一次。

输出

要求输出一个整数,表示坦克从A区到B区的最少移动步数。
如果没有方案,则输出-1

 

样例输入

5
A + - + -
- + - - +
- + + + -
+ - + - +
B + - + -

样例输出

10
#include <bits/stdc++.h>//万能头文件
using namespace std;
 
char Map[101][101]; //地图数组
bool Vis[101][101]; //标记数组 标记是否走过
int Next[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; //方向数组 遍历方向
 
typedef struct node { //定义结构体数组,便于操作调用 包含坐标,步数,符号
	int x, y, step;
	char flag;
} node;
node n[10001]; //BFS数组一般是m*m,再开大一点
 
int main() {
	int m;
	cin >> m;
	getchar(); //吃掉回车
	int head, tail, x, y, tx, ty;
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= m; j++) {
			scanf("%c", &Map[i][j]);
			if (Map[i][j] == 'A') { //记下起点位置的坐标
				x = i, y = j;
			}
			getchar(); //吃掉空格和回车
		}
	}
	head = tail = 1; //初始化 BFS可以理解为一个队列,头和尾
	n[head].x = x;
	n[head].y = y;
	n[head].step = 0;
	n[head].flag = ' ';
	Vis[x][y] = 1; //标记起点位置为走过了
	tail++;
	while (head < tail) { //BFS核心
		for (int i = 0; i < 4; i++) { //遍历4个方向
			tx = n[head].x + Next[i][0];
			ty = n[head].y + Next[i][1];
			if (tx > m || ty > m || tx < 1 || ty < 1) //出边界
				continue;
			if (Vis[tx][ty] == 0 && n[head].flag != Map[tx][ty]) { //没走过且符合+-
				Vis[tx][ty] = 1;
				n[tail].flag = Map[tx][ty];
				n[tail].x = tx;
				n[tail].y = ty;
				n[tail].step = n[head].step + 1;
				tail++;
			}
		}
		if (n[head].flag == 'B') { //走到终点
			cout << n[head].step << endl;
			return 0;
		}
		head++;
	}
	cout << "-1"; //走不到终点
	return 0;
}

111

 222     333

 333

 333331

444

5555

666

777
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怀化第一深情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值