1
POJ 1979 Red and Black
Description
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.
Write a program to count the number of black tiles which he can reach by repeating the moves described above.
Input
The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.
There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.
'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.
Output
For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Sample Output
45
59
6
13
// 红黑两种砖 只能在黑砖上 最多能走多少黑砖
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
int ans;
int dir[4][2]= {{0,1},{0,-1},{-1,0},{1,0}};
char a[25][25];
int m,n;
void dfs(int x,int y)
{
a[x][y] = '#';
++ans;
for(int i = 0 ; i < 4; i ++)
{
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if(dx >= 0 && dx < n && dy >=0 && dy < m && a[dx][dy] == '.')
{
dfs(dx,dy);
}
}
}
int main()
{
while(scanf("%d %d",&m,&n)!=EOF&&m&&n) // m 列 n 行
{
int x,y;
ans = 0;
for(int i = 0 ; i < n ; i++)
for(int j = 0; j < m ;j++)
{
cin>>a[i][j];
if(a[i][j] == '@')
{
x = i;
y = j;
}
}
dfs(x,y);
printf("%d\n",ans);
}
return 0;
}
2
洛谷 P1605 迷宫
题目背景
迷宫 【问题描述】
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和
终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫
中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
输入样例 输出样例
【数据规模】
1≤N,M≤5
题目描述
输入输出格式
输入格式:
【输入】
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点
坐标FX,FY。接下来T行,每行为障碍点的坐标。
输出格式:
【输出】
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方
案总数。
输入输出样例
输入样例#1:
2 2 1
1 1 2 2
1 2
输出样例#1:
1
// 数组从1开始存 起点要注意
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
int m,n,t,sum;
int sx,sy,fx,fy;
int dir[4][2] ={{0,1},{0,-1},{-1,0},{1,0}};
int a[10][10];
void dfs(int x,int y)
{
if(x == fx && y == fy)
{
++sum;
return ;
}
for(int i = 0 ; i < 4; i++)
{
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if(dx >= 1 && dx <= n && dy >= 1 && dy <= m && a[dx][dy] == 1)
{
a[dx][dy] = 0;
dfs(dx,dy);
a[dx][dy] = 1;
}
}
return;
}
int main()
{
int l,r;
sum = 0;
scanf("%d %d %d",&n,&m,&t);
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= n ; j++)
a[i][j] = 1;
scanf("%d %d",&sx,&sy);
scanf("%d %d",&fx,&fy);
for(int i = 0 ; i < t; i ++)
{
scanf("%d %d",&l,&r);
a[l][r] = 0;
}
a[sx][sy] = 0; // 起点要标记走过了~
dfs(sx,sy);
printf("%d\n",sum);
return 0;
}
333
P1219 八皇后
题目描述
检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。
//以下的话来自usaco官方,不代表洛谷观点
特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出(或是找到一个关于它的公式),这是作弊。如果你坚持作弊,那么你登陆USACO Training的帐号删除并且不能参加USACO的任何竞赛。我警告过你了!
输入输出格式
输入格式:
一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。
输出格式:
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入样例#1:
6
输出样例#1:
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
// 关键是存储对角线上是否有棋子找到行,列,阶数n的关系 表示出来
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int a[100]={0},b[100]={0},c[100]={0},d[100]={0}; // 行 列 右上到左下 左上到右下 的 对角线
int ans = 0; // 记录解的个数
void print()
{
if(ans <= 2)
{
for(int k=1;k<=n;k++)
printf("%d ",a[k]);
printf("\n");
}
ans++;//
}
void dfs(int i)
{
if(i > n)
{
print();
return ;
}
else
{
for(int j = 1 ; j <= n ; j++)
{
if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))
{
a[i] = j;
b[j] = 1;
c[i+j] = 1;
d[i - j + n] = 1;
dfs(i + 1);
b[j] = 0;
c[i+j] = 0;
d[i - j + n] = 0;
}
}
}
}
int main()
{
scanf("%d",&n);
dfs(1);
printf("%d\n",ans);
return 0;
}
4444
E - N皇后问题 HDU - 2553
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
// 注意该题要提前将数据打好表来做,要不然会超时
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int a[100]={0},b[100]={0},c[100]={0},d[100]={0}; // 行 列 右上到左下 左上到右下 的 对角线
int ans; // 记录解的个数
int v[15];
void dfs(int i)
{
if(i > n)
{
ans++;
return ;
}
else
{
for(int j = 1 ; j <= n ; j++)
{
if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))
{
a[i] = j;
b[j] = 1;
c[i+j] = 1;
d[i - j + n] = 1;
dfs(i + 1);
b[j] = 0;
c[i+j] = 0;
d[i - j + n] = 0;
}
}
}
}
int main()
{
for(n = 1; n <= 10 ; n++)
{
ans = 0;
dfs(1);
v[n] = ans;
}
int w;
while(scanf("%d",&w)!=EOF&&w)
{
printf("%d\n",v[w]);
}
return 0;
}
55
D - Prime Ring Problem HDU - 1016
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.
Input
n (0 < n < 20).
Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.
Sample Input
6
8
Sample Output
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4
Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int num[100100],v[100100];
int n;
bool isprime(int x) // 判断是否为质数
{
for(int i = 2 ; i <= sqrt(x); i++)
if(x % i == 0)
return false;
return true;
}
void dfs(int x)
{
if(x == n && isprime(num[n - 1]+1)) // 打印
{
printf("1"); // 第一位是1
for(int i = 1; i < n ; i++)
printf(" %d",num[i]);
printf("\n");
}
for(int i = 2;i <= n ; i++)
{
if(!v[i]&&isprime(num[x - 1] + i))
{
num[x] = i;
v[i] = 1;
dfs(x+1);
v[i] = 0;
}
}
}
int main()
{
int k = 1;
while(scanf("%d",&n)!=EOF)
{
memset(v,0,sizeof(v));
num[0] = 1;
v[1] = 1; // 标记1被使用
printf("Case %d:\n",k++);
dfs(1);
printf("\n");
}
return 0;
}