A - Red and Black(POJ 1979)
题意:
一个被方形瓷砖覆盖的矩形房间,瓷砖分为红黑两种颜色。一个人站在一块黑色的瓷砖上,他可以移动到相邻(上,下,左,右)的瓷砖上。但是他不可以移动到红色的瓷砖上。写一个程序计算有多少块黑色的瓷砖这个人可以到达.
包括多组输入,两个零代表输入结束。
输入:’.’代表一块黑色的瓷砖
’#‘代表红色的瓷砖
’@‘代表这个人所在的位置
题解:
根据题意,要找到搜有的可以到达的瓷砖,所有选择深度优先搜索。
#include
#include
#include
#include
using namespace std;
const int N=25;
char tile[N][N];
int d[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int v[N][N];
int w,h,coun;
int judge(int x,int y)
{
return 0<=x&&x0<=y&&y'.';
}
void DFS(int x,int y)
{
int xx,yy;
tile[x][y]='#';
for (int i=0; i<4; i++)
{
xx=x+d[i][0];
yy=y+d[i][1];
if(judge(xx,yy))
{
coun++;
DFS(xx,yy);
}
}
}
int main()
{
while (~scanf("%d %d",&w,&h)&&w&&h)
{
getchar();
int xs=0,ys=0;
for (int i=0; ifor (int j=0; jscanf("%c",&tile[i][j]);
if (tile[i][j]=='@')
{
xs=i;
ys=j;
}
}
getchar();
}
coun=1;
DFS(xs,ys);
printf("%d\n",coun);
}
return 0;
}
B - Lake Counting(POJ 2386)
题意:
因为下雨,农田里积了很多水。一块N×M个小方块的的矩形农田,每个方块分别由‘W’和’.‘组成,W’代表积水,’.‘代表干燥的陆地。农夫现在想知道在他的农田里有多少块水池。如果两个小水池是相邻的则被看成一个水池,一个水池有八个方向。
题解:
深度优先搜寻,遍历每个点是否是W,如果是W,则从这个点开始进行八个方向的深度优先搜寻,被访问过的小水池W标记为‘.’,以后不会再被访问直到把相邻的水池都访问完毕结束搜索,ans++;如果图中还有没被访问的水池,再次进行深搜。
#include
#include
#include
#include
using namespace std;
const int N=120;
char adj[N][N];
int coun;
int w,h;
int d[8][2]= {{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1}};
//判断下标是否越界
int judge(int x,int y)
{
return (0<=x&&x0<=y&&yvoid DFS(int x,int y)
{
int xx,yy;
adj[y][x]='.';//用'.'标记,此块'W'已被访问过
for (int i=0; i<8; i++)
{
xx=x+d[i][0];
yy=y+d[i][1];
if (judge(xx,yy)&&adj[yy][xx]=='W')
{
DFS(xx,yy);
}
}
}
int main()
{
int ans;
while (~scanf("%d %d",&h,&w))
{
if (h==0)
break;
getchar();
for (int i=0; iscanf("%s",adj[i]);
}
ans=0;
for (int i=0; ifor (int j=0; jif (adj[i][j]=='W')
{
DFS(j,i);
ans++;//访问完一块连接的水,ans++
}
}
}
printf("%d\n",ans);
}
return 0;
}
C-变形课(HDU 1181)
题意: 中文题意不解释
题解: 为了方便搜索把每个单词的第一个字母和最后一个单词存进数组里,然后进行深搜就可以了。
#include
#include
#include
#include
using namespace std;
char s[50];
char c[1000][2];//用来存每个单词的开头和结尾
int v[1000];
int flag;
void dfs(int i,int n)
{
if (c[i][1]=='m')
{
flag=1;
return ;
}
for (int j=0; jif (v[j]==0&&c[j][0]==c[i][1])
{
v[ j ]=1;
dfs(j,n);
//v[j]=0;不用回溯,因为当你查到某个单词结束时就说明这条线已经走不通了,所以说这个单词就没必要再查了
}
}
}
int main()
{
int i=0,j;
while (~scanf("%s",s))
{
flag=0;
memset(c,0,sizeof(c));
c[0][0]=s[0];
c[0][1]=s[strlen(s)-1];
i=1;
while (~scanf("%s",s))
{
if (s[0]=='0')
break;
c[ i ][0]=s[0];
c[ i ][1]=s[strlen(s)-1];
i++;
}
for ( j=0; jif (c[ j ][0]=='b')
{
dfs(j,i);
}
}
if (flag)
printf("Yes.\n");
else
printf("No.\n");
}
return 0;
}
D-Rescue(HDU 1242)
题意: 天使被抓进了监狱,监狱是N*M的矩形,监狱里有WALLs, ROADs, and GUARDs 。天使的朋友想救天使出来,想救天使出来就要到达天使被关的监狱的房间。路途中可能遇见GUARDs,他们要杀死GUARDs,在监狱里天使的朋友可以上,下,左,右移动,每移动一次花费的时间是一分钟,杀死守卫花费的时间也是一分钟,问要救出天使所花费的最短时间是多久。
“.” 代表路,,”a” 代表天使, “r” 代表每个人天使的朋友,”x”代表守卫,”#”代表墙。
题解: 根据题意要找最短时间,所以用广度优先搜索。注意使用优先队列,应为杀死守卫要多花费一分钟。
//代码
#include
#include
#include
#include
#include
#include
using namespace std;
const int inf=0x3f3f3f3f;
const int N=250;
int w,h;
int xs,ys; //起始位置
int flag; //是否找到angel
char moli[N][N];
int v[N][N];
int d[][2]= {{0,1},{-1,0},{0,-1},{1,0}}; //方向
struct P
{
int x,y,step;
friend bool operator < (P a,P b)
{
return a.step>b.step;
}
} ;
//struct cmp
//{
// bool operator () (P a,P b)
// {
// return a.step>b.step;
// }
//};
//判断是否超出城堡界限
int judge(int x,int y)
{
if( x<0 || y<0 || x>h || y>w )
return 0;
if(v[x][y])
return 0;
if( moli[x][y]=='#' )
return 0;
return 1;
}
/*广度优先搜素是利用队列实现*/
void BFS()
{
P a,b;
flag=0;
memset(v,0,sizeof v);
v[xs][ys]=1;
a.x=xs;
a.y=ys;
a.step=0;
priority_queueQ;
Q.push(a);
while (!Q.empty())
{
a=Q.top();
Q.pop();
/*找到angel输出时间*/
if (moli[a.x][a.y]=='a')
{
printf("%d\n",a.step);
flag=1;
break;
}
/*判断一个格子的上,下,左,右是否可走*/
for (int i=0; i<4; i++)
{
b.x=a.x+d[i][0];
b.y=a.y+d[i][1];
if (judge(b.x,b.y))
{
if (moli[b.x][b.y]=='x')
b.step=a.step+2;//这里就是为什么要用优先队列
else
b.step=a.step+1;
v[b.x][b.y]=1;
Q.push(b);
}
}
}
}
int main()
{
while (~scanf("%d %d",&h,&w))
{
for (int i=0; ifor (int j=0; jscanf("%c",&moli[i][j]);
if (moli[i][j]=='r')
xs=i,ys=j;
}
getchar();
}
BFS();
if (!flag)
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
return 0;
}
E-Catch That Cow(POJ 3278)
题意:
John的一头牛跑了,Joh想马上抓住他。John在点n,奶牛在点k。n,k在同一条线上。John有两种移动方式:walking and teleporting。
Walking:可以从点x移动到点x-1或者x+1.
Teleporting:可以从点X移动到2*x。
奶牛是不动的。移动一次的需要一分钟,问John最短多久可以抓住奶牛。
题解:
根据题意要找最短时间,所以要用广度优先搜索。队列里存放的是John,每一步位置的坐标。要注意的一点是,虽然数据量是1e5 但是John可以移动到他2*x的位置。所以John可能会移动到2e5的位置,所以数组要开到2e5。
#include
#include
#include
#include
#include
using namespace std;
const int N=2e5+7;
int v[N];//标记x是否已被走过
int coun[N];//记录走到x所用的时间
int n,k;
void bfs()
{
queue<int > Q;
int x;
Q.push(n);
v[n]=1;
while (!Q.empty())
{
x=Q.front();
Q.pop();
if (x==k)
break;
if (x+1<=k&&!v[x+1])
{
Q.push(x+1);
coun[ x+1 ]=coun[ x ]+1;
v[x+1]=1;
}
if (x-1>=0&&!v[x-1])
{
Q.push(x-1);
coun[ x-1 ]=coun[ x ]+1;
v[x-1]=1;
}
if (x*2<2*k&&!v[x*2])
{
Q.push(x*2);
coun[ x*2 ]=coun[ x ]+1;
v[x*2]=1;
}
}
}
int main()
{
while (~scanf("%d %d",&n,&k))
{
memset(v,0,sizeof(v));
memset(coun,0,sizeof(coun));
bfs();
printf("%d\n",coun[k]);
}
return 0;
}