主题:递归与回溯的常见题目(选自GCC入门题集)
wuchengwei
[专家分:1650] 发布于 2006-06-19 11:19:00
//////////////////////////////////////////////////////////////////////////////
//
// 4. 在N行N列的数阵中, 数K(1〈=K〈=N)在每行和每列中出现且仅
// 出现一次,这样的数阵叫N阶拉丁方阵。例如下图就是一个五阶拉丁方阵。
// 编一程序,从键盘输入N值后,打印出所有不同的N阶拉丁方阵,并统计个数。
//
// 1 2 3 4 5
// 2 3 4 5 1
// 3 4 5 1 2
// 4 5 1 2 3
// 5 1 2 3 4
//////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
#define N 4
static int a[N][N], count;
bool legal(int row, int col)
{
int i;
for(i = 0; i < row; i++)
{
if(a[i][col] == a[row][col])
return false;
}
for(i = 0; i < col; i++)
{
if(a[row][i] == a[row][col])
return false;
}
return true;
}
void trial(int row, int col, FILE *fp)
{
int i, j;
if(row == N)
{
printf("*********** %d **********\n", ++count);
fprintf(fp, "*********** %d **********\n", count);
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
printf("%5d", a[i][j]);
fprintf(fp, "%5d", a[i][j]);
}
putchar(10);
fputc(10, fp);
}
}
for(i = 1; i <= N; ++i)
{
a[row][col] = i;
if(legal(row, col))
trial((row*N+col+1)/N, (row*N+col+1)%N, fp);
}
}
void main()
{
FILE *fp = fopen("latin.txt", "w");
trial(0, 0, fp);
}
//////////////////////////////////////////////////////////////////////////////
//
// 11. 巧排数字。将1、2、...、20这20个数排成一排,使得相邻的两个数之
// 和为一个素数,且首尾两数字之和也为一个素数。编程打印出所有的排法。
//////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
#include "math.h"
static used[21], link[21];
bool isprime(int a)
{
for(int i = 2; i <= sqrt(a); i++)
{
if(!(a%i))
return false;
}
return true;
}
void trace(int node)
{
int i;
if((node == 21) && isprime(link[20] + link[1]))
{
for(i = 1; i < 21; i++)
printf("%4d", link[i]);
putchar(10);
}
for(i = 1; i <= 20; i++)
{
if(!used[i])
{
link[node] = i;
used[i] = 1;
if(isprime(link[node]+link[node-1]))
trace(node+1);
used[i] = 0;
}
}
}
void main()
{
trace(1);
}
回复列表 (共5个回复)
沙发
wuchengwei [专家分:1650] 发布于 2006-06-19 11:20:00
//////////////////////////////////////////////////////////////////////////////
//
// 15. 已知6个城市,用c[i,j]表示从i城市到城市j是否有单向的直达汽车
//
// (1=<i〈=6,1〈=j〈=6), c[i,j]=1 表示城市i到城市j有单向直达汽
// 车; 否则 c[i,j]=0. 试编制程序,对于给出的城市代号i,打印出从该城市出
// 发乘车(包括转车)可以到达的所有城市。
//////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
#define N 6
int visited[N] = {0};
void visit(int c[][N], int i)
{
if(!visited[i])
{
visited[i] = 1;
for(int j = 0; j < N; j++)
if(c[i][j] && !visited[j])
visit(c, j);
}
}
void main( void )
{
int c[N][N], i, j, n;
srand((unsigned)time(NULL));
for (i = 0; i < N; i++ )
{
for(j = 0; j < N; j++)
{
c[i][j] = rand()%2;
printf( "%6d", c[i][j]);
}
putchar('\n');
}
scanf("%d", &n);
assert(n < N);
visit(c, n);
for (i = 0; i < N; i++ )
{
if(visited[i])
printf( "%6d", i);
}
}
//////////////////////////////////////////////////////////////////////////////
//
// 20. (N皇后) 在国际象棋的棋盘上放置N个皇后,使其不能互相攻击,即任意
// 两个皇后不能处在棋盘的同一行,同一列,同一斜线上,试问共有多少种摆法?
//////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
#include "conio.h"
#define N 8
static int a[N][N], count;
bool legal(int row, int col)
{
int i, j;
for(i = 0; i < row; i++)
if(a[i][col])
return false;
for(j = 0; j < col; j++)
if(a[row][j])
return false;
for(i = row-1, j = col-1; (i>=0) &&(j>=0); i--, j--)
if(a[i][j])
return false;
for(i = row-1, j = col+1; (i>=0) &&(j<N); i--, j++)
if(a[i][j])
return false;
return true;
}
void trial(int row)
{
int p, col;
if(row == N)
{
++count;
printf("********%d*********\n", count);
for(p = 0; p < N; p++)
{
for(col = 0; col < N; col++)
printf("%4d", a[p][col]);
printf("\n");
}
}
else
{
for(col = 0; col < N; col++)
{
a[row][col] = 1;
if(legal(row, col))
trial(row+1);
a[row][col] = 0;
}
}
}
void main()
{
trial(0);
}
板凳
wuchengwei [专家分:1650] 发布于 2006-06-19 11:23:00
//////////////////////////////////////////////////////////////////////////////
//
//21. 请设计一个程序,由计算机把1.. ̄.8的八个自然数填入图中,使得横、
// 竖、对角任何两个相邻的小方格中的两个数是不连续的。(下图右侧的 4 个图
// 为禁止的情形).
//
// ┌─┐ ┌─┐ ┌─┐
// │ │ │4│ │8│
// ┌─┼─┼─┐ └─┼─┐ ┌─┼─┘
// │ │ │ │ │5│ │7│
// ├─┼─┼─┤ └─┘ └─┘
// │ │ │ │ ┌─┐
// └─┼─┼─┘ │6│ ┌─┬─┐
// │ │ ├─┤ │1│2│
// └─┘ │7│ └─┴─┘
// └─┘
//////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
#include "string.h"
#include "math.h"
int a[4][3];
int count = 0;
bool legalelem(int row, int col)
{
switch (row)
{
case 0:
case 3:
if(col == 1)
return true;
else
return false;
case 1:
default:
return true;
}
}
bool islegal(int row, int col)
{
int i, j;
for(i = row-1; i <= row+1; i++)
{
if(i < 0 || i > 3)
continue;
for(j = col-1; j <= col+1; j++)
{
if(j < 0 || j > 2)
continue;
if(abs(a[i][j] - a[row][col]) == 1)
return false;
}
}
return true;
}
void trace(int n)
{
int i, j;
if(n > 8)
{
++count;
printf("\n********** %d **********\n", count);
for(i = 0; i < 4; i++)
{
for(j = 0; j < 3; j++)
{
if(legalelem(i, j))
printf("%6d", a[i][j]);
else
printf("%*s", 6, "");
}
putchar(10);
}
return;
}
for(i = 0; i < 4; i++)
{
for(j = 0; j < 3; j++)
{
if(a[i][j] == -1 && legalelem(i, j))
{
a[i][j] = n;
if(islegal(i, j))
trace(n+1);
a[i][j] = -1;
}
}
}
}
void main()
{
int i, j;
for(i = 0; i < 4; i++)
for(j = 0; j < 3; j++)
a[i][j] = -1;
trace(1);
}
3 楼
wuchengwei [专家分:1650] 发布于 2006-06-19 11:24:00
//////////////////////////////////////////////////////////////////////////////
//
// 22. 在一个4*4的小方格(如图所示)中放置8个*号,使得每行每列放且
// 仅放两个*号。
//
// ┌─┬─┬─┬─┐
// │*│*│ │ │
// ├─┼─┼─┼─┤
// │*│ │*│ │
// ├─┼─┼─┼─┤
// │ │*│ │*│
// ├─┼─┼─┼─┤
// │ │ │*│*│
// └─┴─┴─┴─┘
//
// 求出所有的基本解。
//////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
#define N 4
static int a[N][N], count;
bool legal(int row, int col)
{
int sum, p;
for(sum = 0, p = 0; p < row; p++)
sum += a[p][col];
if(sum < 2)
{
for(sum = 0, p = 0; p < col; p++)
sum += a[row][p];
if(sum < 2)
return true;
else
return false;
}
else
return false;
}
void trial(int row)
{
if(row == N)
{
++count;
printf("******** %d ********\n", count);
for(int p = 0; p < N; p++)
{
for(int q = 0; q < N; q++)
printf("%4d", a[p][q]);
printf("\n");
}
}
else
{
for(int j1 = 0; j1 < N-1; j1++)
{
a[row][j1] = 1;
if(legal(row, j1))
{
for(int j2 = j1+1; j2 < N; j2++)
{
if(!a[row][j2])
{
a[row][j2] = 1;
if(legal(row, j2))
trial(row+1);
a[row][j2] = 0;
}
}
}
a[row][j1] = 0;
}
}
}
void main()
{
trial(0);
}
4 楼
wuchengwei [专家分:1650] 发布于 2006-06-19 11:25:00
//////////////////////////////////////////////////////////////////////////////
//
// 38. 有一集合中有 N 个元素,每个元素均为自然数。给定一个 total (假设每个
// 元素值均小于total),求满足条件的所有子集,子集中各元素之和应等于total。
//////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
int a[] = {1, 2, 3, 4, 7, 10};
const int N = sizeof(a)/sizeof(int);
void trial(int i,int j, int a[], int b[], int total)
{
if(i == N) //不能和下面的if(b[0] == total)合写成if(i == N && b[0] == total),因为这个if为递推的回归条件语句,要单独做判断,如果和写的话,则只有当i ==N且
b[0] == total 时条件才为真时递推过程才结束
{
if(b[0] == total)
{
for(int p = 1; p < j; p++)
printf("%5d", b[p]);
printf("\n");
}
}
else
{
b[0] += a[i];
b[j] = a[i];
trial(i+1, j+1, a, b, total);
b[0] -= a[i];
b[j] = 0;
trial(i+1, j, a, b, total);
}
}
void main()
{
int *b = new int[N], i, total;
printf("a[%d] = {", N);
for(i = 0; i < N; i++)
printf(" %d,", a[i]);
printf("}\ninput the total, insure its value larger than each element of array a:");
scanf("%d", &total);
b[0] = 0;
trial(0, 1, a, b, total);
}
5 楼
wuchengwei [专家分:1650] 发布于 2006-06-19 11:29:00
大家继续添加
我来回复