Jzoj 函数与递归部分代码(共27题)

1302: 【入门】挛生素数

#include <bits/stdc++.h>
using namespace std;
int n;
//判断x是否为质数 
bool check(int x)
{
	for(int i=2; i<=sqrt(x); ++i){
		if(x%i==0){
			return false;
		}
	} 
	return true;
}
int main()
{
	scanf("%d", &n);
	for(int i=2; i<=n-2; ++i){
		if(check(i) && check(i+2)){
			printf("%d %d\n", i, i+2);
		}
	}
	return 0;
}

1087: 【入门】哥德巴赫猜想

#include <bits/stdc++.h>
using namespace std;
int n, total, prim[200];
//判断x是否为质数 
bool check(int x)
{
	for(int i=2; i<=sqrt(x); ++i){
		if(x%i==0){
			return false;
		}
	} 
	return true;
}
int main()
{
	scanf("%d", &n);
	for(int i=2; i<=n; ++i){
		if(check(i)){
			total++;
			prim[total]=i;
		}
	}
	for(int i=4; i<=n; i+=2){
		//将i分解为两个质数的和
		for(int j=1; j<=total; ++j){
			for(int k=j; k<=total; ++k){
				if(i==prim[j]+prim[k]){
					printf("%d=%d+%d\n", i, prim[j], prim[k]); 
				}
			}
		} 
	}
	return 0;
}

1100: 【入门】等差素数组

#include <bits/stdc++.h>
using namespace std;
int n, total, mid, prim[100];
bool vis[100];
//判断x是否为质数 
bool check(int x)
{
	for(int i=2; i<=sqrt(x); ++i){
		if(x%i==0){
			return false;
		}
	} 
	return true;
}
int main()
{
	//先求出100以内的质数 
	for(int i=2; i<=100; ++i){
		if(check(i)){
			total++;	//总共有total个质数 
			prim[total]=i;
			vis[i]=true;	//将质数标记为true 
		}
	}
	for(int i=1; i<total; ++i){	//枚举质数 
		for(int j=i+1; j<=total; ++j){	//枚举后面的质数 
			if((prim[i]+prim[j])%2){	//如果两个质数之和不是偶数, 直接跳过 
				continue;
			}
			mid=(prim[i]+prim[j])/2;	//计算平均值 
			if(vis[mid]){	//如果平均值也是质数, 则输出 
				printf("%d %d %d\n", prim[i], mid, prim[j]);
			}
		} 
	}
	return 0;
}

1097: 【入门】素数回文数

#include <bits/stdc++.h>
using namespace std;
//判断x是否为质数 
bool check(int x)
{
	for(int i=2; i<=sqrt(x); ++i){
		if(x%i==0){
			return false;
		}
	} 
	return true;
}
//判断一个数是否是回文数 
bool palindromic(int x)
{
	int length=0, num[4];	//length记得初始化 
	//数位分离, 将每一位保存在数组中 
	while(x){
		length++;
		num[length]=x%10;
		x/=10;
	} 
	for(int i=1; i<=length; ++i){
		if(num[i]!=num[length-i+1]){
			return false;
		}
	}
	return true;
}
int main()
{
	for(int i=10; i<=1000; ++i){
		if(check(i) && palindromic(i)){
			printf("%d\n", i);
		}
	}
	return 0;
}

1076: 【基础】机器人的逻辑

#include <bits/stdc++.h>
using namespace std;
int n, a[51];
bool flag;
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		scanf("%d", &a[i]);
	}
	sort(a+1, a+n+1); 
	for(int i=a[1]; i>=1; --i){
		flag=true;
		for(int j=1; j<=n; ++j){
			if(a[j]%i!=0){
				flag=false;
				break;
			}
		}
		if(flag==true){
			printf("%d", i);
			return 0;
		}
	}
	return 0;
}

1140: 【基础】亲密数对

#include <bits/stdc++.h>
using namespace std;
int n;
//计算x的因子之和 
int sum(int x)
{
	int asd=0;
	for(int i=2; i<=sqrt(x); ++i){
		//如果i是x的因子 
		if(x%i==0){
			asd+=i;
			asd+=x/i;	
		}
		if(i*i==x){
			asd-=i;
		}
	} 
	return asd;
}
int main()
{
	scanf("%d", &n);
	for(int i=2; i<=n; ++i){
		int temp=sum(i);
		if(temp!=i && sum(temp)==i && temp<=n){
			printf("%d %d\n", i, temp);
		} 
	}
	return 0;
}

2000: 【基础】因子游戏

#include <bits/stdc++.h>
using namespace std;
int k, a[81];
//计算x的因子之和 
int sum(int x)
{
	int asd=0;
	for(int i=1; i<=sqrt(x); ++i){
		//如果i是x的因子 
		if(x%i==0){
			asd+=2;	
		}
		if(i*i==x){
			asd--;
		}
	} 
	return asd;
}
//输出x的约数 
void print(int x)
{
	printf("%d\n", x);
	for(int i=1; i<=x; ++i){
		//如果i是x的因子 
		if(x%i==0){
			printf("%d ", i);
		}
	} 
}
int main()
{
	scanf("%d", &k);
	for(int i=1; i<=20000; ++i){
		if(sum(i)==k){ 
			print(i);
			return 0; 
		} 
	}
	printf("NO SOLUTION");
	return 0;
}

1153: 【基础】经典递归问题——汉诺塔

#include <bits/stdc++.h>
using namespace std;
int n, cnt;
void asd(int n, char a, char b, char c)
{
	if(n==1){
		printf("%c To %c\n", a, c);
		cnt++;
	}
	else{
		asd(n-1, a, c, b);
		printf("%c To %c\n", a, c);
		cnt++;
		asd(n-1, b, a, c);
	}
}
int main()
{
	scanf("%d", &n);
	asd(n, 'A', 'B', 'C');
//	printf("最少步数为:%d", cnt);
	return 0;
}

2801: 【基础】聪明的海宝

#include <bits/stdc++.h>
using namespace std;
int n;
//计算第w个沙坑中的金币数 
int ans(int w)
{
	if(w==1){
		return 1;
	}
	//偶数 
	if(w%2==0){
		return ans(w/2)+w; 
	}
	else{	//奇数 
		return ans(3*w+1)+w; 
	}
}
int main()
{
	scanf("%d", &n);
	printf("%d", ans(n));
	return 0;
}

1844: 【USACO】Symmetry(对称)

#include <bits/stdc++.h>
using namespace std;
int n, m;
int solve(int x, int y)
{
	//有一个是偶数, 就没有中心格子了 
	if(x%2==0 || y%2==0){
		return 0; 
	}
	else{	//找到一个中心格子, 并继续划分 
		return 1+4*solve(x/2, y/2); 
	}
}
int main()
{
	scanf("%d %d", &n, &m);
	printf("%d", solve(n, m));
	return 0;
}

1571: 【NOIP98普及组】2的幂次方

方法一:递归

#include <bits/stdc++.h>
using namespace std;
int n;
void solve(int x)
{
	int flag=-1;
	int cnt=0, a[20];
	memset(a, 0, sizeof(a));
	//先对x进行二进制拆分
	//将十进制x转换为二进制
	while(x){
		a[cnt]=x%2; 	//从a[0]开始保存最低位 
		if(x%2!=0 && flag==-1){
			flag=cnt;	//flag表示二进制数非0的最低位
		}
		x>>=1;	//幂运算, 相当于x/=2; 
		cnt++;
	} 
	//从最高位开始, 对非0项进行递归输出 
	for(int i=cnt-1; i>=0; --i){
		if(a[i]==0){
			continue;
		} 
		else{
			if(i==0){	//已经到最低位了, 2的0次直接输出, 递归出口 
				printf("2(0)");
				return;
			}
			else if(i==1){	//2的1次, 题目要求直接输出2 
				printf("2");	//注意, 此时不能直接return, 有可能还有2的0次 
				if(i>flag){		//判断, 如果此时不是最低位, 则需要输出+ 
					printf("+");
				}
			}
			else{	//一路递归下去 
				printf("2(");  
				solve(i);	//递归函数要放在中间 
				printf(")");
				if(i>flag){		//判断, 如果此时不是最低位, 则需要输出+ 
					printf("+");
				}	
			} 
		}
	}
}
int main()
{
	scanf("%d", &n);
	solve(n);	
	return 0;
}

方法二:打表

#include <iostream>
using namespace std;
int n, a[100], length, cnt;
//打表 
string s[17]={"0", "", "2", "2+2(0)", "2(2)", "2(2)+2(0)", "2(2)+2", "2(2)+2+2(0)", "2(2+2(0))", "2(2+2(0))+2(0)", "2(2+2(0))+2",
			  "2(2+2(0))+2+2(0)", "2(2+2(0))+2(2)", "2(2+2(0))+2(2)+2(0)", "2(2+2(0))+2(2)+2", "2(2+2(0))+2(2)+2+2(0)", "2(2(2))"};
int main()
{
	cin >> n;
	//将十进制数n转换为二进制数,存在a数组中,a[0]存低位
	//length记录二进制有几位 
	while(n){
		a[length]=n%2;
		n/=2;
		length++;
	}
	//计算转换后的二进制中有多少个1,也就是最后的式子中有cnt-1个加号 
	for(int i=0; i<length; ++i){
		if(a[i]!=0){
			cnt++; 
		}
	}
	cnt--;
	//将二进制中位数为1的位输出 
	for(int i=length-1; i>=0; --i){
		//位数为1,并且不是2^1那一位 
		if(a[i]!=0 && i!=1){
			cout << "2(" << s[i] << ")";
			if(cnt!=0){	//如果这个式子后面还有式子,则输出一个加号 
				cout << "+";
				cnt--;
			}
		}
		else if(a[i]!=0 && i==1){ //位数为1,并且是2^1那一位 
			cout << "2";
			if(cnt!=0){	//如果这个式子后面还有式子,则输出一个加号
				cout << "+";
				cnt--;
			}
		}
	}

	return 0;
}

2342: 【提高】递归

#include <bits/stdc++.h>
using namespace std;
long long a, b, c, ans[21][21][21];
long long w(long long x, long long y, long long z)
{
	if(x<=20 && y<=20 && z<=20 && x>=0 && y>=0 && z>=0 && ans[x][y][z]){
		return ans[x][y][z];
	}
	if(x<=0 || y<=0 || z<=0){
		return 1;
	}
	else if(x>20 || y>20 || z>20){
		return w(20, 20, 20);
	}
	else if(x<y && y<z){
		return ans[x][y][z]=w(x,y,z-1)+w(x,y-1,z-1)-w(x,y-1,z);
	}
	else{
		return ans[x][y][z]=w(x-1,y,z)+w(x-1,y-1,z)+w(x-1,y,z-1)-w(x-1,y-1,z-1);
	}
}
int main()
{
	while(1){
		scanf("%lld %lld %lld", &a, &b, &c);
		if(a==-1 && b==-1 && c==-1){
			return 0;
		}
		memset(ans, 0, sizeof(ans));
		printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, w(a, b, c));
	}
	return 0;
} 

1091: 【提高】那些n位数

方法一:循环

//循环方法 
#include <bits/stdc++.h>
using namespace std;
int n, p;
int main()
{
	scanf("%d %d", &n, &p);
	if(n==1){
		for(int i=1; i<=p; ++i){
			printf("%d\n", i);
		}
	}
	else if(n==2){
		for(int i=1; i<=p; ++i){
			for(int j=1; j<=p; ++j){
				printf("%d%d\n", i, j);
			}
		}
	}
	else if(n==3){
		for(int i=1; i<=p; ++i){
			for(int j=1; j<=p; ++j){
				for(int k=1; k<=p; ++k){
					printf("%d%d%d\n", i, j, k);
				}
			}
		}
	}
	else if(n==4){
		for(int i=1; i<=p; ++i){
			for(int j=1; j<=p; ++j){
				for(int k=1; k<=p; ++k){
					for(int l=1; l<=p; ++l){
						printf("%d%d%d%d\n", i, j, k, l);
					}
				}
			}
		}	
	}
	else if(n==5){
		for(int i=1; i<=p; ++i){
			for(int j=1; j<=p; ++j){
				for(int k=1; k<=p; ++k){
					for(int l=1; l<=p; ++l){
						for(int m=1; m<=p; ++m){
							printf("%d%d%d%d%d\n", i, j, k, l, m);
						}
					}
				}
			}
		}
	}
	else if(n==6){
		for(int i=1; i<=p; ++i){
			for(int j=1; j<=p; ++j){
				for(int k=1; k<=p; ++k){
					for(int l=1; l<=p; ++l){
						for(int m=1; m<=p; ++m){
							for(int o=1; o<=p; ++o){
								printf("%d%d%d%d%d%d\n", i, j, k, l, m, o);
							}	
						}
					}
				}
			}
		}
	}
	else if(n==7){
		for(int i=1; i<=p; ++i){
			for(int j=1; j<=p; ++j){
				for(int k=1; k<=p; ++k){
					for(int l=1; l<=p; ++l){
						for(int m=1; m<=p; ++m){
							for(int o=1; o<=p; ++o){
								for(int q=1; q<=p; ++q){
									printf("%d%d%d%d%d%d%d\n", i, j, k, l, m, o, q);
								}
							}	
						}
					}
				}
			}
		}
	}
	else if(n==8){
		for(int i=1; i<=p; ++i){
			for(int j=1; j<=p; ++j){
				for(int k=1; k<=p; ++k){
					for(int l=1; l<=p; ++l){
						for(int m=1; m<=p; ++m){
							for(int o=1; o<=p; ++o){
								for(int q=1; q<=p; ++q){
									for(int r=1; r<=p; ++r){
										printf("%d%d%d%d%d%d%d%d\n", i, j, k, l, m, o, q, r);
									}
								}
							}	
						}
					}
				}
			}
		}
	}
	return 0;
}

方法二:递归

#include <bits/stdc++.h>
using namespace std;
int n, p, a[10];
void solve(int cnt)
{
	if(cnt==n+1){
		for(int i=1; i<=n; ++i){
			printf("%d", a[i]);
		}
		printf("\n");
		return;
	}
	for(int i=1; i<=p; ++i){
		a[cnt]=i;
		solve(cnt+1);
	}
}
int main()
{
	scanf("%d %d", &n, &p);
	solve(1);
	return 0;
}

2023: 【提高】那些n位数II

#include <bits/stdc++.h>
using namespace std;
int n, p, a[10];
bool vis[10];
void solve(int cnt)
{
	if(cnt==n+1){
		for(int i=1; i<=n; ++i){
			printf("%d", a[i]);
		}
		printf("\n");
		return;
	}
	for(int i=1; i<=p; ++i){
		if(vis[i]==false){
			a[cnt]=i;	
			vis[i]=true;
			solve(cnt+1);
			vis[i]=false;
		}
	}
}
int main()
{
	scanf("%d %d", &n, &p);
	solve(1);
	return 0;
}

2025: 【提高】生成组合

方法一:循环

//循环方法 
#include <bits/stdc++.h>
using namespace std;
int n, p;
int main()
{
	scanf("%d %d", &p, &n);
	if(n==1){
		for(int i=1; i<=p; ++i){
			printf("%d\n", i);
		}
	}
	else if(n==2){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				printf("%d%d\n", i, j);
			}
		}
	}
	else if(n==3){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				for(int k=j+1; k<=p; ++k){
					printf("%d%d%d\n", i, j, k);
				}
			}
		}
	}
	else if(n==4){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				for(int k=j+1; k<=p; ++k){
					for(int l=k+1; l<=p; ++l){
						printf("%d%d%d%d\n", i, j, k, l);
					}
				}
			}
		}	
	}
	else if(n==5){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				for(int k=j+1; k<=p; ++k){
					for(int l=k+1; l<=p; ++l){
						for(int m=l+1; m<=p; ++m){
							printf("%d%d%d%d%d\n", i, j, k, l, m);
						}
					}
				}
			}
		}
	}
	else if(n==6){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				for(int k=j+1; k<=p; ++k){
					for(int l=k+1; l<=p; ++l){
						for(int m=l+1; m<=p; ++m){
							for(int o=m+1; o<=p; ++o){
								printf("%d%d%d%d%d%d\n", i, j, k, l, m, o);
							}	
						}
					}
				}
			}
		}
	}
	else if(n==7){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				for(int k=j+1; k<=p; ++k){
					for(int l=k+1; l<=p; ++l){
						for(int m=l+1; m<=p; ++m){
							for(int o=m+1; o<=p; ++o){
								for(int q=o+1; q<=p; ++q){
									printf("%d%d%d%d%d%d%d\n", i, j, k, l, m, o, q);
								}
							}	
						}
					}
				}
			}
		}
	}
	else if(n==8){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				for(int k=j+1; k<=p; ++k){
					for(int l=k+1; l<=p; ++l){
						for(int m=l+1; m<=p; ++m){
							for(int o=m+1; o<=p; ++o){
								for(int q=o+1; q<=p; ++q){
									for(int r=q+1; r<=p; ++r){
										printf("%d%d%d%d%d%d%d%d\n", i, j, k, l, m, o, q, r);
									}
								}
							}	
						}
					}
				}
			}
		}
	}
	else if(n==9){
		for(int i=1; i<=p; ++i){
			for(int j=i+1; j<=p; ++j){
				for(int k=j+1; k<=p; ++k){
					for(int l=k+1; l<=p; ++l){
						for(int m=l+1; m<=p; ++m){
							for(int o=m+1; o<=p; ++o){
								for(int q=o+1; q<=p; ++q){
									for(int r=q+1; r<=p; ++r){
										for(int s=r+1; s<=p; ++s){
											printf("%d%d%d%d%d%d%d%d%d\n", i, j, k, l, m, o, q, r, s);
										}
									}
								}
							}	
						}
					}
				}
			}
		}
	}
	return 0;
}

方法二:递归

#include <iostream>
using namespace std;
int n, r;
int a[21];
void dfs(int cnt)
{
	if(cnt==r+1){
		for(int i=1; i<=r; i++)
			printf("%d", a[i]);
		printf("\n");
		return;
	}
	for(int i=a[cnt-1]+1; i<=n-r+cnt; i++){		//n-r+cnt写成n也可以 
		a[cnt]=i;	 
		dfs(cnt+1);
	}
}
int main()
{
	cin >> n >> r;
	dfs(1);
	return 0;
}

1648: 【提高】素数个数

#include <bits/stdc++.h>
using namespace std;
int n, r;
int num[21], a[21], sum, ans;
bool check(int x)
{
	if(x<2){
		return false;
	}
	for(int i=2; i<=sqrt(x); ++i){
		if(x%i==0){
			return false;
		}
	}
	return true;
}
void dfs(int cnt)
{
	if(cnt==r+1){
		sum=0;
		for(int i=1; i<=r; i++)
			sum+=num[a[i]];
		if(check(sum)){
			ans++;
		}
		return;
	}
	for(int i=a[cnt-1]+1; i<=n-r+cnt; i++){		//n-r+cnt写成n也可以 
		a[cnt]=i;	 
		dfs(cnt+1);
	}
}
int main()
{
	scanf("%d %d", &n, &r);
	for(int i=1; i<=n; ++i){
		scanf("%d", &num[i]);
	}
	dfs(1);
	printf("%d", ans);
	return 0;
}

2026: 【提高】自然数拆分

#include <bits/stdc++.h>
using namespace std;
int n, a[15], num;
struct node
{
	int asd[15];
	int tot;
	long long id;	
}ans[100];
bool cmp(node x, node y)
{
	return x.id>y.id; 
}
//将x分为total个整数, 当前准备分第cnt个整数 
void dfs(int x, int cnt, int total)
{
	//将x分为total个数, 现在准备安排第cnt个, 如果第cnt个等于total 
	if(cnt==total){	//如果要将x分为一个数, 直接赋值为x 
		if(x<a[cnt-1])	return;		//避免重复 
		a[cnt]=x;
		num++;
		ans[num].tot=total;
		for(int i=total; i>=1; --i){
			ans[num].asd[i]=a[i];
			ans[num].id+=a[i]*pow(10,n+i-total);
		}
	}
	else{
		//还没分完, 如果分的是第一个, 则从1开始枚举, 此时的a[cnt-1]为0
		//如果分的不是第一个, 则从前一个值开始枚举 
		for(int i=max(1, a[cnt-1]); i<=x; ++i){
			a[cnt]=i;
			dfs(x-i, cnt+1, total);
		}
	}
	
} 
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		//将n分为i个整数之和, 当前准备分安排第一个 
		dfs(n, 1, i);	
	}
	sort(ans+1, ans+num+1, cmp);
	for(int i=1; i<=num; ++i){
		for(int j=ans[i].tot; j>=1; --j){
			printf("%3d", ans[i].asd[j]);
		} 
		printf("\n");
	}
	return 0;
}

2027: 【提高】自然数拆分II

#include <bits/stdc++.h>
using namespace std;
int n, a[15], num;
struct node
{
	int asd[15];
	int tot;
	long long id;	
}ans[100];
bool cmp(node x, node y)
{
	return x.id<y.id; 
}
//将x分为total个整数, 当前准备分第cnt个整数 
void dfs(int x, int cnt, int total)
{
	//将x分为total个数, 现在准备安排第cnt个, 如果第cnt个等于total 
	if(cnt==total){	//如果要将x分为一个数, 直接赋值为x 
		if(x<a[cnt-1])	return;		//避免重复 
		a[cnt]=x;
		num++;
		ans[num].tot=total;
		for(int i=1; i<=total; ++i){
			ans[num].asd[i]=a[i];
			ans[num].id+=a[i]*pow(10,n-i);
		}
	}
	else{
		//还没分完, 如果分的是第一个, 则从1开始枚举, 此时的a[cnt-1]为0
		//如果分的不是第一个, 则从前一个值开始枚举 
		for(int i=max(1, a[cnt-1]); i<=x; ++i){
			a[cnt]=i;
			dfs(x-i, cnt+1, total);
		}
	}
	
} 
int main()
{
	scanf("%d", &n);
	for(int i=2; i<=n; ++i){
		//将n分为i个整数之和, 当前准备分安排第一个 
		dfs(n, 1, i);	
	}
	sort(ans+1, ans+num+1, cmp);
	for(int i=1; i<=num; ++i){
		for(int j=1; j<=ans[i].tot; ++j){
			printf("%3d", ans[i].asd[j]);
		} 
		printf("\n");
	}
	return 0;
}

1494: 【USACO】"跳房子"

#include <bits/stdc++.h>
using namespace std;
int a[10][10], ans;
bool vis[1000000];
//跳到了x行y列, 当前是第cnt个数, 此前的和为cur 
void dfs(int x, int y, int cnt, int cur)
{
	//跳到界外 
	if(x<1 || y<1 || x>5 || y>5){
		return;
	}
	if(cnt==6){	//已经是第6个数了 
		//累加
		cur=cur*10+a[x][y];
		if(vis[cur]==false){
			ans++;
			vis[cur]=true;
		}
		return;
	} 
	else{	//还没跳够6个数 
		cur=cur*10+a[x][y]; 
		dfs(x-1, y, cnt+1, cur);
		dfs(x+1, y, cnt+1, cur);
		dfs(x, y-1, cnt+1, cur);
		dfs(x, y+1, cnt+1, cur);
	}
}
int main()
{
	for(int i=1; i<=5; ++i){
		for(int j=1; j<=5; ++j){
			scanf("%d", &a[i][j]);
		} 
	}
	for(int i=1; i<=5; ++i){
		for(int j=1; j<=5; ++j){
			dfs(i, j, 1, 0);
		} 
	}
	printf("%d", ans); 
	return 0;
} 

1666: 【基础】发书

#include <bits/stdc++.h>
using namespace std;
int k, n, m, from, to;
//n<250,m<10000
//这道题数据范围有问题, 数组开到250会出错, 改为251就过了 
bool vis[251], flag;
bool know[251][251];
void dfs(int id)
{
	for(int i=1; i<=n; ++i){
		//如果id认识i, 并且还没给i发书 
		if(know[id][i] && !vis[i]){
			vis[i]=true;
			//让i去发书 
			dfs(i);
		}
	}
}
int main()
{
	//k代表star的学号,n代表人数,m代表关系数
	scanf("%d %d %d", &k, &n, &m);
	while(m--){
		scanf("%d %d", &from, &to);
		know[from][to]=true;
	}
	vis[k]=true;
	dfs(k);
	for(int i=1; i<=n; ++i){
		if(!vis[i]){
			printf("%d ", i);
			flag=true;
		}
	} 
	if(flag==false){
		printf("0");
	}
	return 0;
} 

1168: 【提高】老鼠闯迷宫

#include <bits/stdc++.h>
using namespace std;
int m, n;
int a[20][20];	//1表示有障碍物 
int ans[200][3];	//ans[i][1]表示第i步的行, ans[i][2]表示第i步的列 
bool vis[20][20];	//标记是否走过 
int mx[9]={0, 1, 0, -1, -1, -1, 0, 1, 1};
int my[9]={0, 1, 1, 1, 0, -1, -1, -1, 0}; 
void dfs(int x, int y, int cnt)
{
	//出界 或者 有障碍物 
	if(x<1 || y<1 || x>m || y>n || a[x][y]==1){
		return;
	}
	//到达终点 
	if(x==m && y==n){
		//输出路径 
		ans[cnt][1]=x;
		ans[cnt][2]=y;
		for(int i=1; i<=cnt; ++i){
			printf("(%d,%d)", ans[i][1], ans[i][2]);
			if(i!=cnt){
				printf("-");
			}
		}
		exit(0);	//结束程序 
	}
	//还没到达终点
	ans[cnt][1]=x;
	ans[cnt][2]=y;
	//标记 
	vis[x][y]=true;
	for(int i=1; i<=8; ++i){
		int xx=x+mx[i];
		int yy=y+my[i];
		if(!vis[xx][yy]){
			dfs(xx, yy, cnt+1);
		}
	} 
	//回溯 
	vis[x][y]=false;
}
int main()
{
	//m行n列 
	scanf("%d %d", &m, &n);
	for(int i=1; i<=m; ++i){	//行 
		for(int j=1; j<=n; ++j){	//列 
			scanf("%d", &a[i][j]);	//1表示有障碍物 
		}
	}
	vis[1][1]=true;
	//从第一行第一列出发, 走了一个格子 
	dfs(1, 1, 1); 
	return 0;	
} 

1167: 【提高】跳马

//这道题关于输出的描述有问题, 题目描述输出一条路径,
//实际需要输出所有的路径, 每行一条 
#include <bits/stdc++.h>
using namespace std;
int m, n;
int a[20][20];	//1表示有障碍物 
int ans[200][3];	//ans[i][1]表示第i步的行, ans[i][2]表示第i步的列 
bool vis[20][20];	//标记是否走过 
int mx[9]={0, 2, 1, -1, -2, -2, -1, 1, 2};
int my[9]={0, 1, 2, 2, 1, -1, -2, -2, -1}; 
void dfs(int x, int y, int cnt)
{
	//出界 或者 有障碍物 
	if(x<1 || y<1 || x>m || y>n || a[x][y]==1){
		return;
	}
	//到达终点 
	if(x==m && y==n){
		//输出路径 
		ans[cnt][1]=x;
		ans[cnt][2]=y;
		for(int i=1; i<=cnt; ++i){
			printf("(%d,%d)", ans[i][1], ans[i][2]);
			if(i!=cnt){
				printf("-");
			}
		}
		printf("\n");
//		exit(0);	//结束程序 
		return; 
	}
	//还没到达终点
	ans[cnt][1]=x;
	ans[cnt][2]=y;
	//标记 
	vis[x][y]=true;
	for(int i=1; i<=8; ++i){
		int xx=x+mx[i];
		int yy=y+my[i];
		if(!vis[xx][yy]){
			dfs(xx, yy, cnt+1);
		}
	} 
	//回溯 
	vis[x][y]=false;
}
int main()
{
	//m行n列 
	scanf("%d %d", &m, &n);
	for(int i=1; i<=m; ++i){	//行 
		for(int j=1; j<=n; ++j){	//列 
			scanf("%d", &a[i][j]);	//1表示有障碍物 
		}
	}
	vis[1][1]=true;
	//从第一行第一列出发, 走了一个格子 
	dfs(1, 1, 1); 
	return 0;	
} 

1846: 【USACO】Space Exploration

#include <bits/stdc++.h>
using namespace std;
int n;
char a[1002][1002];
bool vis[1002][1002];
int ans;
void dfs(int x, int y)
{
	if(a[x+1][y]=='*' && !vis[x+1][y]){
		vis[x+1][y]=true;
		dfs(x+1, y);
	}
	if(a[x-1][y]=='*' && !vis[x-1][y]){
		vis[x-1][y]=true;
		dfs(x-1, y);
	}
	if(a[x][y+1]=='*' && !vis[x][y+1]){
		vis[x][y+1]=true;
		dfs(x, y+1);
	}
	if(a[x][y-1]=='*' && !vis[x][y-1]){
		vis[x][y-1]=true;
		dfs(x, y-1);
	}
}
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		for(int j=1; j<=n; ++j){
			cin >> a[i][j];
		}
	}
	for(int i=1; i<=n; ++i){
		for(int j=1; j<=n; ++j){
			//i行j列为岛屿, 并且没被其他岛屿包含进去 
			if(a[i][j]=='*' && !vis[i][j]){
				ans++;
				dfs(i, j);
			} 
		}
	}
	printf("%d", ans);
	return 0;	
} 

1495: 【USACO】卫星照片

#include <bits/stdc++.h>
using namespace std;
int w, h;
char a[1002][82];
bool vis[1002][82];
int cur, ans;
void dfs(int x, int y)
{
	if(a[x+1][y]=='*' && !vis[x+1][y]){
		vis[x+1][y]=true;
		cur++;
		dfs(x+1, y);
	}
	if(a[x-1][y]=='*' && !vis[x-1][y]){
		vis[x-1][y]=true;
		cur++;
		dfs(x-1, y);
	}
	if(a[x][y+1]=='*' && !vis[x][y+1]){
		vis[x][y+1]=true;
		cur++;
		dfs(x, y+1);
	}
	if(a[x][y-1]=='*' && !vis[x][y-1]){
		vis[x][y-1]=true;
		cur++;
		dfs(x, y-1);
	}
}
int main()
{
	scanf("%d %d", &w, &h);
	for(int i=1; i<=h; ++i){
		for(int j=1; j<=w; ++j){
			cin >> a[i][j];	//字符数组输入用cin 
		}
	}
	for(int i=1; i<=h; ++i){
		for(int j=1; j<=w; ++j){
			//i行j列为牧场, 并且没被其他牧场包含进去 
			if(a[i][j]=='*' && !vis[i][j]){
				vis[i][j]=true;
				//每次找牧场时初始化当前这片牧场的面积 
				cur=1;
				dfs(i, j);
				//找完与i行j列连续的牧场, 更新答案 
				ans=max(ans, cur);
			} 
		}
	}
	printf("%d", ans);
	return 0;	
} 

2028: 【提高】8皇后问题

方法一

#include <bits/stdc++.h>
using namespace std;
//a[i]存的是第i行的棋子放的列,我们的目标就是把1-n分配给a[1]-a[n],并且不能冲突 
//vis[i][j]=1表示第i行第j列放了棋子,为0表示没放棋子
//vis1[i]=1表示第i列有棋子了,为0表示第i列没有棋子 
int n, a[14], vis[14][14], vis1[14];
//在x行y列放会不会产生冲突 
bool ok(int x, int y)
{
	//定义临时遍历,不然x,y的值在一次while判断后就改变了,导致后面的判断失效 
	int tempx, tempy;	
	//判断同一行、同一列有没有冲突 
	//其实没有必要判断行(因为每行只安排一个数),没有必要判断列(vis1[i]表示第i列有没有数字) 
	/*
	for(int i=1; i<=n; ++i){
		if(vis[x][i]==1 || vis[i][y]==1){
			return false;
		}
	}
	*/
	tempx=x;
	tempy=y;
	//判断左下角有没有冲突 
	while(tempx!=n && tempy!=1){
		tempx++;
		tempy--;
		if(vis[tempx][tempy]==1){
			return false;
		}
	}
	tempx=x;
	tempy=y;
	//判断右上角有没有冲突 
	while(tempx!=1 && tempy!=n){
		tempx--;
		tempy++;
		if(vis[tempx][tempy]==1){
			return false;
		}
	} 
	tempx=x;
	tempy=y;
	//判断左上角有没有冲突 
	while(tempx!=1 && tempy!=1){
		tempx--;
		tempy--;
		if(vis[tempx][tempy]==1){
			return false;
		}
	}
	tempx=x;
	tempy=y;
	//判断右下角有没有冲突 
	while(tempx!=n && tempy!=n){
		tempx++;
		tempy++;
		if(vis[tempx][tempy]==1){
			return false;
		}
	}  
	return true;
}
void dfs(int cnt)
{
	if(cnt==n+1){
		for(int i=1; i<=n; ++i){
			cout << a[i] << " ";
		}
		cout << endl;	
	}
	//看第cnt行要放在第几列,i遍历列 
	for(int i=1; i<=n; ++i){
		//如果第cnt行第i列没有放棋子,并且第i列没有放棋子
		//并且在cnt行i列放棋子不会产生冲突,才可以放 
		if(vis[cnt][i]==0 && vis1[i]==0 && ok(cnt, i)){	
			vis[cnt][i]=1;
			vis1[i]=1;
			a[cnt]=i;	
			dfs(cnt+1);
			vis[cnt][i]=0;	
			vis1[i]=0;			
		}
	}
}
int main()
{
	n=8;
	dfs(1);
	return 0;
}

方法二

1154: 【基础】N皇后问题

#include <bits/stdc++.h>
using namespace std;
//a[i]存的是第i行的棋子放的列,我们的目标就是把1-n分配给a[1]-a[n],并且不能冲突 
//vis[i][j]=1表示第i行第j列放了棋子,为0表示没放棋子
//vis1[i]=1表示第i列有棋子了,为0表示第i列没有棋子 
int n, a[14], vis[14][14], vis1[14];
//在x行y列放会不会产生冲突 
bool ok(int x, int y)
{
	//定义临时遍历,不然x,y的值在一次while判断后就改变了,导致后面的判断失效 
	int tempx, tempy;	
	//判断同一行、同一列有没有冲突 
	//其实没有必要判断行(因为每行只安排一个数),没有必要判断列(vis1[i]表示第i列有没有数字) 
	/*
	for(int i=1; i<=n; ++i){
		if(vis[x][i]==1 || vis[i][y]==1){
			return false;
		}
	}
	*/
	tempx=x;
	tempy=y;
	//判断左下角有没有冲突 
	while(tempx!=n && tempy!=1){
		tempx++;
		tempy--;
		if(vis[tempx][tempy]==1){
			return false;
		}
	}
	tempx=x;
	tempy=y;
	//判断右上角有没有冲突 
	while(tempx!=1 && tempy!=n){
		tempx--;
		tempy++;
		if(vis[tempx][tempy]==1){
			return false;
		}
	} 
	tempx=x;
	tempy=y;
	//判断左上角有没有冲突 
	while(tempx!=1 && tempy!=1){
		tempx--;
		tempy--;
		if(vis[tempx][tempy]==1){
			return false;
		}
	}
	tempx=x;
	tempy=y;
	//判断右下角有没有冲突 
	while(tempx!=n && tempy!=n){
		tempx++;
		tempy++;
		if(vis[tempx][tempy]==1){
			return false;
		}
	}  
	return true;
}
void dfs(int cnt)
{
	if(cnt==n+1){
		for(int i=1; i<=n; ++i){
			for(int j=0; j<=n; ++j){
				if(j==a[i]){
					cout << " Q";
				}
				else if(j==0){
					printf("%2d", n-i+1); 
				}
				else{
					cout << "  ";
				}
			}
			cout << endl;
		}
		printf("   a");	
		for(int i=1; i<=n-1; ++i){
			printf("%2c", 'a'+i);
		}
		cout<<endl<<endl;
	}
	//看第cnt行要放在第几列,i遍历列 
	for(int i=1; i<=n; ++i){
		//如果第cnt行第i列没有放棋子,并且第i列没有放棋子
		//并且在cnt行i列放棋子不会产生冲突,才可以放 
		if(vis[cnt][i]==0 && vis1[i]==0 && ok(cnt, i)){	
			vis[cnt][i]=1;
			vis1[i]=1;
			a[cnt]=i;	
			dfs(cnt+1);
			vis[cnt][i]=0;	
			vis1[i]=0;			
		}
	}
}
int main()
{
	cin >> n;
	dfs(1);
	return 0;
}

1313: 【USACO】城堡

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ypeijasd

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

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

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

打赏作者

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

抵扣说明:

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

余额充值