冬令营搜索专题

A - 棋盘问题

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

Input

输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

Output

对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。

Sample Input

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

Sample Output

2

1

#include<iostream> using namespace std; const int N=9; char a[N][N]; bool col[N]={0}; int n,k; int m; int ans; void dfs(int t) { if(m==k) { ans++; return ; } if(t==n) return ; for(int i=0;i<n;i++) { if(!col[i]&&a[t][i]=='#') { col[i]=1; m++; dfs(t+1); col[i]=0; m--; } } dfs(t+1); } int main() { while(cin>>n>>k,n!=-1&&k!=-1) { m=ans=0; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) cin>>a[i][j]; } dfs(0); cout<<ans<<endl; } return 0; }

C - 全排列

给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 我们假设对于小写字母有 'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中的字母已经按照从小到大的顺序排列。

输入格式

输入只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在 11 到 66 之间。

输出格式

输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:

已知 S = s_1s_2...s_k, T = t_1t_2...t_kS=s1​s2​...sk​,T=t1​t2​...tk​,则 S < TS<T 等价于,存在 p (1 \le p \le k)p(1≤p≤k),使得 s_1 = t_1, s_2 = t_2, ..., s_{p - 1} = t_{p - 1}, s_p < t_ps1​=t1​,s2​=t2​,...,sp−1​=tp−1​,sp​<tp​ 成立。

Sample Input

abc

Sample Output

abc
acb
bac
bca
cab
cba

#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll N=1e6+1e5; char s[N]; signed main() { cin>>s; cout<<s<<"\n"; ll l=strlen(s); ll k=1; for(ll i=1;i<=l;i++) k*=i; k--; for(ll i=1;i<=k;i++) { next_permutation(s,s+l); cout<<s<<"\n"; } }

M - 八皇后问题

努比亚和苏丹没有子女,所以他要从一些有集成资格的继承者中挑选一个出来继承王位。他希望这个继承者足够聪明,所以他准备了一个西洋棋盘,上面的每个格子中均有一个 1-991−99 的数字。他又准备了 88 个皇后棋子。

88 皇后的规则就是不能有任何棋子同行或者同列或者同斜线,在满足这个规则的同时,王位继承者还需要让 88 个皇后所在的位置的数字的和是最大的。

输入格式

输入一个数字 k(k\leq 20)k(k≤20),代表棋盘的数量。

接下来有 kk 个棋盘,每个棋盘有 6464 个数字,分成 88 行 88 列出入,具体可见样例,每一个数字均小于 100100。

输出格式

每一个棋盘对应输出最大的数值, 一共输出 kk 行。

Sample Input

1
 1  2  3  4  5  6  7  8
 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
48 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64

Sample Output

260
#include<iostream>
using namespace std;
const int N=18;
int a[N][N];
bool col[N];
bool g[N],ug[N];
int ans;
int m=0;
void dfs(int t)
{
	if(t==8)
	{
		m=max(m,ans);
		return ;
	}
	for(int i=0;i<8;i++)
	{
		if(!col[i]&&!g[t-i+8]&&!ug[t+i])
		{
			ans+=a[t][i];
			col[i]=g[t-i+8]=ug[t+i]=1;
			dfs(t+1);
			col[i]=g[t-i+8]=ug[t+i]=0;
			ans-=a[t][i];
		}
	}
}
int main()
{
	int k;
	cin>>k;
	while(k--)
	{
		m=0;
		ans=0;
		g[N]=0;
		ug[N]=0;
		for(int i=0;i<8;i++)
		{
			for(int j=0;j<8;j++)
			cin>>a[i][j];
		}
		dfs(0);
		cout<<m<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值