冬令营 Winter Camp搜索专题
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冬令营 Winter Camp搜索专题相关的知识,希望对你有一定的参考价值。
【冬令营 Winter Camp】搜索专题
- A - 棋盘问题
- B - Perket
- C - 全排列
- D - 自然数拆分
- E - Prime Ring Problem
- F - Red and Black
- G - Knight Moves
- H - Oil Deposits
- I - Lake Counting
- J - 二叉树先序遍历
- K - 迷宫(一)
- L - 马走日
- M - 八皇后问题
- N - 选数
- O - 打开灯泡 Switch the Lamp On
- 总结
A - 棋盘问题
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Sample Input
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
2
1
思路:深度优先遍历,一行一行判断能否放棋子,每一行需要判断每一列能否放能放,能放/不能放
也都递归到下一行(这样能包含所有放棋子的情况),注意回溯。
Java
import java.util.Scanner;
public class Main
static int n, k, cnt;
static char[][] array;
static boolean[] used;
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
while (sc.hasNext())
n = sc.nextInt();
k = sc.nextInt();
if (n == -1 && k == -1)
break;
cnt = 0;
array = new char[n][n];
used = new boolean[n];
sc.nextLine();
for (int i = 0; i < n; i++)
array[i] = sc.nextLine().toCharArray();
dfs(0, 0);
System.out.println(cnt);
public static void dfs(int i, int sum)
if (i == n)
if (sum == k)
cnt++;
return;
for (int j = 0; j < n; j++)
if (array[i][j] == '.')
continue;
if (!used[j])
used[j] = true;
dfs(i+1, sum+1);
used[j] = false;
dfs(i+1, sum);
C++
#include<iostream>
#include<string.h>
using namespace std;
int n, k, cnt;
char a[10][10];
bool flag[10];
void dfs(int x, int sum)
if (x == n)
if (sum == k)
cnt++;
return;
// 遍历一行的每一列,判断能否放棋子
for (int i = 0; i < n; i++)
if (a[x][i] == '.' || flag[i]) // 如果当前x,i位置为.或者是所在行列已经被占用则跳过
continue;
flag[i] = true; // 修改标记数组
dfs(x+1, sum+1); // 放一枚棋子递归下一行
flag[i] = false; // 回溯
// 这一行不放棋子,跳过(模拟所有)
dfs(x+1, sum);
int main()
while (1)
cin >> n >> k;
if (n == -1 && k == -1)
break;
// 每次测试都需要修改全局变量的初始值
memset(flag, false, sizeof(flag));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> a[i][j];
cnt = 0;
dfs(0, 0);
printf("%d\\n", cnt);
return 0;
B - Perket
你有 N 种配料,每种配料有酸度 S 和苦度 B 。用这些配料做成Perket时,总的酸度为所有配料酸度的乘积,总的苦度是所有配料苦度的和。你至少需要添加一种配料。
为了使口感适中,总的酸度和苦度之差的绝对值应该尽可能小,求这个最小值。
4
1 7
2 6
3 8
4 9
1
Java
import java.util.Scanner;
public class Main
static int n, k, cnt;
static int[][] array;
static boolean[] used;
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
array = new int[n][2];
cnt = Integer.MAX_VALUE;
for (int i = 0; i < n; i++)
array[i][0] = sc.nextInt();
array[i][1] = sc.nextInt();
dfs(0, 1, 0, 0);
System.out.println(cnt);
public static void dfs(int i, int a, int b, int k)
if (i == n)
if (k > 0)
cnt = Math.min(cnt, Math.abs(a - b));
return;
dfs(i+1, a*array[i][0], b + array[i][1], k+1);
dfs(i+1, a, b, k);
C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1E5 + 7;
ll current_exception = 1e9+10;
ll arr[10][2];
ll n, k, cnt = 1e9+1;
void dfs(ll i, ll a, ll b)
if (i == n)
if (k > 0)
cnt = min(cnt, abs(a - b));
return;
k++;
dfs (i + 1, a * arr[i][0], b + arr[i][1]);
k--;
dfs(i + 1, a, b);
int main()
cin >> n;
for (int i = 0; i < n; i++)
cin >> arr[i][0] >> arr[i][1];
dfs(0, 1, 0);
cout << cnt;
思路:n<=10,数据较小,暴力求解,每一个都试试加入和不加入两种情况,取最小值,来源:大佬博客
#include<iostream>
#include<cmath>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long int ll;
typedef pair<ll,ll> P;
const int maxn=200100;
const int INF=pow(2,31)-1;
const int maxm=5e4+5;
const int mod=1000000007;
ll n;
ll s[maxn],b[maxn];
ll ans,cnt;
ll mi=1e9+10;
/*bool judge(ll x)
for(int i=1;i<=n;i++)
*/
void dfs(ll step,ll k)
if(step==n+1)
if(k>=1)mi=min(mi,abs(ans-cnt));
return ;
ans*=s[step];
cnt+=b[step];
dfs(step+1,k+1);
cnt-=b[step];
ans/=s[step];
dfs(step+1,k);
return ;
int main()
cin>>n;
for(int i=1;i<=n;i++)
cin>>s[i]>>b[i];
ans=1;
dfs(1,0);
cout<<mi<<endl;
return 0;
C - 全排列
给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。我们假设对于小写字母有’a’< ‘b’< …<‘y’<‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。
输入格式
输入只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。
输出格式
输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。
abc
abc
acb
bac
bca
cab
cba
Java
import java.util.Scanner;
public class Main
static int n, k, cnt;
static int[][] array;
static char[] arr;
static boolean[] used;
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
arr = sc.nextLine().toCharArray();
used = new boolean[arr.length];
Arrays.sort(arr);
fullSort(new StringBuilder());
public static void fullSort(StringBuilder res)
if (res.length() == arr.length)
System.out.println(res.toString());
return;
for (int i = 0; i < arr.length; i++)
if (!used[i])
used[i] = true;
res.append(arr[i]);
fullSort(res);
res.deleteCharAt(res.length()-1);
used[i] = false;
C++
#include<iostream>
#include<cmath>
#include<string.h> // strlen()
#include<algorithm> // 排序操作
#include<map>
using namespace std;
typedef long long int ll;
typedef pair<ll,ll> P;
const int maxn=200100;
const int INF=pow(2,31)-1;
const int maxm=5e4+5;
const int mod=1000000007;
char str[maxn],st[maxn]; // 字符数组
ll cnt;
ll used[maxn];
ll n;
void dfs(ll step)
// 输出结果
if(step==n+1)
for(int i=1;i<=cnt;i++)
cout<<st[i];
cout<<endl;
return ;
for(int i=1;i<=n;i++)
if(!used[i])
used[i]=1;
st[++cnt]=str[i];
dfs(step+1);
used[i]=0;
cnt--;
return ;
int main()
cin>>(str+1);
n=strlen(str+1);
sort(str+1,str+1+n);
dfs(1);
return 0;
D - 自然数拆分
对于任意大于 1 的自然数 n,总是可以拆分成若干个小于 n 的自然数之和。
现请你编写程序求出 n 的所有拆分。
5
5=1+1+1+1+1
5=1+1+1+2
5=1+1+3
5=1+2+2
5=以上是关于冬令营 Winter Camp搜索专题的主要内容,如果未能解决你的问题,请参考以下文章