1.UVa 572紫书题目,作为熟悉DFS之用
//dfs uva572
const int maxn = 100 + 5;
char pic[maxn][maxn];
int m,n,idx[maxn][maxn];
void dfs(int r,int c,int id){
if(r<0||r>=m||c<0||c>=n) return; //出界的格子
if(idx[r][c]>0||pic[r][c]!='@') return; //不是@或已经访问过
idx[r][c] = id; //联通分量编号
for(int dr = -1;dr<=1;dr++)
for(int dc=-1;dc<=1;dc++)
if(dr!=0||dc!=0) dfs(r+dr,c+dc,id);//只要不是原地不动
}
int main(){
while(scanf("%d%d",&m,&n)==2&&m&&n){
for(int i=0;i<m;i++) scanf("%s",pic[i]);
memset(idx,0,sizeof(idx));
int cnt = 0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(idx[i][j]==0&&pic[i][j]=='@') dfs(i,j,++cnt);
printf("%d\n",cnt);
}
return 0;
}
2.PAT 1003 emergency
其实是最短路题,但是用DFS可以做,在DFS的代码上改动一下即可。
花了好多时间做这个题,对DFS掌握的还是不够熟练啊,对一些枝上的细节处理不够好,一直通过部分案例。好在最后终于改好了。
其实有个小问题,这个DFS是存在环的,比如从0→1→0→2,在进入DFS前把起始点访问就好了,但是不用这么做也可以,因为求最短路,这种重复计算的路径肯定是会被排除在外的。
//1003 DFS改动
int n,c1,c2,a[505],path[505][505],vis[505];
int cnt,mincost,cost,maxteams,teams;
void DFS(int i){
//printf("当前点%d 路径长度%d 最短路径数%d\n",i,cost,cnt);
if(i == c2)
{
if(cost<mincost) {
//printf("新的最短路%d\n",cost);
cnt=1;
mincost = cost;
maxteams = teams;
}
else if(cost==mincost) {
//printf("重复的最短路径%d\n",cost);
cnt++;
if(teams>maxteams)
maxteams = teams;
}
return;
}
if(cost>mincost) return;//如果没到目标但是已经花费比之前的最短大了,就剪掉
int j;
for(j = 0; j < n; j++){
if(path[i][j] != -1 && !vis[j]){
cost+=path[i][j];
teams += a[j];
vis[j] = 1;
DFS(j);
vis[j]=0;
cost -= path[i][j];
teams -= a[j];
}
}
}
int main(){
int m,loc1,loc2,w;
while(scanf("%d%d%d%d",&n,&m,&c1,&c2)!=EOF){
for(int i=0;i<n;i++) scanf("%d",&a[i]);
memset(path,-1,sizeof(path));
memset(vis,0,sizeof(vis));
for(int i=0;i<m;i++){
scanf("%d%d%d",&loc1,&loc2,&w);
path[loc1][loc2] = path[loc2][loc1] = w;
}
mincost = INT_MAX;
cnt = 0;
teams = a[c1];
cost = 0;
//vis[c1]=1;
DFS(c1);
printf("%d %d\n",cnt,maxteams);
}
return 0;
}