第1关:排列
Sample Input
4 2
Sample Output
A B
A C
A D
B A
B C
B D
C A
C B
C D
D A
D B
D C
分析:
注意 是所有情况的枚举
解题代码:
//#include<bits/stdc++.h>
#include<stdio.h>
//using namespace std;
int m,n;
int an[10010],a[10010],ck[10010];
void cal(int x){
if(x==n){
for(int i = 0;i<n;i++){
printf("%c",an[i]); if(i!=n-1) printf(" ");
}
printf("\n");
return;
}else{
for(int i = 0 ; i < m;i++){
if(ck[i]!=1){
an[x] = a[i];
ck[i] = 1;
cal(x+1);
ck[i] = 0;
}
}
}
}
int main(){
scanf("%d%d",&m,&n);
for(int i = 0; i <m;i++){
a[i] = i+ 'A';
ck[i] = 0;
}
cal(0);
return 0;
}
第2关: 子集合
Sample Input
5 10
2 2 6 5 4
Sample Output
2 2 6
6 4
思路: 就是一个子集树 找到符合条件的子集的限定条件就可以了
解题代码:
#include<stdio.h>
//#include<bits/stdc++.h>
//using namespace std;
int a[20],an[20], ck[20];
int n,c;
int f = 0;
void solve(int x,int sum,int st){
if(sum>c) return; //剪枝
if(sum==c){
f = 1;//标记是不是 存在解
for(int i = 0; i <x;i++){
//输出
printf("%d",an[i]); if(i!=x-1) printf(" ");
} printf("\n");
return;
}else{
for(int i = st; i <n;i++){
//解空间树结点下的结点 是有范围的
if(ck[i]!=1){
an[x] = a[i]; ck[i] = 1;
//cout<<"i: "<<i<<" "<<a[i]<<" "<<sum<<" "<<ck[i]<<endl;
solve(x+1,sum+a[i],i);
ck[i] = 0;
}
}
}
}
int main(){
scanf("%d%d",&n,&c);
for(int i = 0; i < n;i++) scanf("%d",&a[i]);
solve(0,0,0);
if(!f) printf("No Solution!");
return 0;
}
第3关:TSP问题
输入格式
第一行输入n,代表有n个城市。
接下来n行每行输入n个数,第i行j列的值代表i市到j市的距离,0代表城市之间不通
注意:起点和终点都为1
n<7,城市之间的距离都不超过100
输出格式
第一行输出最少的旅行费用
第二行输入旅行路径
(保证只有一条最短旅行路径)
Sample Input
4
0 30 6 4
30 0 5 10
6 5 0 20
4 10 20 0
Sample Output
25
1 3 2 4 1
代码一:
// #include<bits/stdc++.h>
// using namespace std;
#include<stdio.h>
int a[110][110];
int n;
int f[110],p[110],pd[110];
int minn = 1000010,sum = 0,len = 1;
void solve(int x){
if(len==n&&a[x][1]!=0){
//就是 最后要回到起点
if(sum+a[x][1]<minn){
for(int i = 0; i<n;i++){
pd[i] = p[i]; //存一下 不断更新 找最小的
}
minn = sum +a[x][1];
}
}
if(sum>minn) return ;
if(len<n){
for(int j = 1; j <= n;j++){
if(f[j]==0&&a[x][j]!= 0){
sum += a[x][j]; p[len] = j;
len++; f[j] = 1;
solve(j);
f[j] = 0;
len--;
sum -= a[x][j];
}
}
}
}
int main(){
scanf("%d",&n);
for(int i = 1; i <= n;i++){
for(int j = 1; j <= n;j++){
scanf("%d",&a[i][j]);
}
}
f[1] = 1; solve(1);
printf("%d\n",minn);
printf("1 ");
for(int i = 1; i < n;i++) printf("%d ",pd[i]);
printf("1");
return 0;
}
代码二:
#include <stdio.h>
#define MAX 100
int n;
int b[8]={
1,2,3,4,5,6,7};
int a[MAX][MAX],x[8];
int mindis=1000;
void swap(int &a,int &b)
{
int t=a;
a=b;
b=t;
}
void dfs(int i,int dis)
{
if(dis>=mindis)
return;
else if(i==n)
{
if(dis+a[b[i-1]][1]<mindis)
{
mindis=dis+a[b[i-1]][1];
for(int j=1;j<n;j++)
x[j]=b[j];
}
return;
}
else
{
for(int j=i;j<n;j++)
{
swap(b[i],b[j]);
dfs(i+1,dis+a[b[i-1]][b[i]]);
swap(b[i],b[j]);
}
}
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
}
dfs(1,0);
printf("%d\n",mindis);
printf("1");
for(int i=1;i<n;i++)
printf(" %d",x[i]);
printf(" 1");
return 0;
}
第4关:n皇后问题
任务描述
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
输入格式
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
输出格式
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
任务描述
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
输入格式
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
输出格式
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
思路:
其实解空间树的限制条件 ,就是在这条解的集合上,判断当前节点的所在行、斜线和反斜线上是不是已经有皇后了。
解题代码:
//#include<bits/stdc++.h>
#include<stdio.h>
//using namespace std;
const int N = 20;
int n;
int col[N],dg[N],udg[N];
int ans;
void solve(int u){
if(u==n){
ans++; return;
}else{
for(int i = 0; i< n;i++){
if(!col[i]&&!dg[u+i]&&!udg[u+n-i]){
col[i] = dg[u+i] = udg[u+n-i] = true;
solve(u+1);
col[i] = dg[u+i] = udg[u+n-i] = false;
}
}
}
}
int main(){
while(~scanf("%d",&n)&&n){
ans = 0;
solve(0);
printf("%d\n",ans);
}
return 0;
}
第5关:0-1背包
**思路:**就是拿动态规划过的 没啥好说的
解题代码:
#include<stdio.h>
// #include<bits/stdc++.h>
// using namespace std;
int n,c,w[110],v[110];
int f[110][110];
int main(){
scanf("%d%d",&n,&c);
for(int i = 1; i <= n;i++){
scanf("%d",&w[i]);
}
for(int i = 1; i <= n;i++){
scanf("%d",&v[i]);
}
for(int i = 1; i <= n;i++){
for(int j = 0; j <= c;j++){
f[i][j] = f[i-1][j];
if(j>=w[i]&&(f[i-1][j-w[i]]+v[i] > f[i][j])) f[i][j] = f[i-1][j-w[i]]+v[i] ;
}
}
printf("%d",f[n][c]);
return 0;
}