2017.1.20
A - Oil Deposits HUD-1241
题目概括:在一个m*n的网格区域中,对于每一小格,如果有石油为’@’,该小格称为pocket,如果没有石油则为’*’。若两个pocket相邻(水平,垂直或斜),则为同一油田。求给定区域内有多少不同的油田。
约束: 1<=m<=100,1<=n<=100,结束信号为m=0。
思路:【求有几个连通区域】
依次找未标记的’@’,进行DFS,每探索到相邻的未标记的’@’都标记一下,该点探索完毕就用num计数++。所有’@’都标记完了,结果为num。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char a[101][101];
int book[101][101];//标志数组,全局变量初始化为0
int n,m,num;
void dfs(int x,int y,int num)
{
int next[8][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
if(x<0||x>=n||y<0||y>=m) return;
if(a[x][y]!='@'||book[x][y]!=0) return;
book[x][y]=1;
for(int i=0;i<8;i++)
dfs(x+next[i][0],y+next[i][1],num);
return;
}
int main()
{
cin>>n>>m;
while(~scanf("%d%d",&n,&m))
{
if(m==0) return 0;
num=0;
//标志数组清零,memset引用头文件<cstring>
memset(book,0,sizeof(book));
for(int i=0;i<n;i++)
scanf("%s",a[i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(a[i][j]=='@'&&book[i][j]==0)
{
num++;
dfs(i,j,num);
}
}
cout<<num<<endl;
}
return 0;
}
B - Prime Ring Problem HDU-1016
题目概括:给定n, 把自然数1,2,3,…,n构成一个圆环,相邻两数之和为质数。第一个数必须是1。
约束: 0 < n < 20
思路:【DFS】
因为第一个数已经规定了必须是1,即探索下一个数时已知前一个数,只需判断该数和前一个数之和是否是素数,只有到达第n个数时,还需判断和后一个数,即1,之和是否为素数。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
using namespace std;
int a[202],book[202];
int n;
bool sushu(int m) //素数判别
{
for(int i=2;i<=sqrt(m);i++)
if(m%i==0) return 0;
return 1;
}
void dfs(int step) //站在step个位置上上
{
if(step>n)
{
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
return;
}
for(int i=2;i<=n;i++) //数字
if(book[i]==0&&(sushu(a[step-1]+i)))
if(step<n||(step==n&&sushu(1+i)))
{
a[step]=i;
book[i]=1;
dfs(step+1);
book[i]=0; //标志还原
}
return;
}
int main()
{
int k=0;
while(~scanf("%d",&n))
{
a[1]=1;book[1]=1;
printf("Case %d:\n",++k);
dfs(2);
printf("\n");
}
return 0;
}
C - 棋盘问题 POJ-1321
题目概括:在给定棋盘上摆放棋子,要求任意两个棋子不能在同一列或同一行,求有多少种摆放方案c。在n*n区域内表示棋盘,棋盘用’#’表示,棋子有k个。
约束: n <= 8 , k <= n
思路:【类似八皇后问题】
因为每行只有一个棋子,所以放置的时候按照追行放置的顺序,每放置一个棋子,标志该列。注意DFS递归返回,返回上一层,要把这层列标志取消。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
char a[9][9];
int book[9]; //列标志
int n,k,c,num;
void dfs(int x)
{
if(num==k)
{
c++;
return;
}
if(x>n) return;
for(int i=0;i<n;i++) //逐行放置
if(a[x][i]=='#'&&book[i]==0)
{
book[i]=1;
num++;
dfs(x+1);
book[i]=0; //返回后取消标志
num--;
}
dfs(x+1);
return;
}
int main()
{
while(~scanf("%d%d",&n,&k))
{
if(n==-1&&k==-1) return 0;
c=0;num=0;
for(int i=0;i<n;i++)
scanf("%s",a[i]);
dfs(0);
printf("%d\n",c);
}
return 0;
}