专题链接:https://cn.vjudge.net/contest/65959
A - 棋盘问题
题意:在棋盘上放k个棋子的方案数。要求每行每列至多只有一个。
思路:DFS。详见代码。
#include <cstdio> using namespace std; char m[10][10]; int n,k; int ans; void dfs(int x,int y,int num) { if(num==k) { ans++; return; } while(x<=n) { if(m[x][y]=='#') { int flag=1; for(int j=1;j<=n;j++) if(m[j][y]=='*'||m[x][j]=='*') flag=0; if(flag==1) { m[x][y]='*'; dfs(x,y,num+1); m[x][y]='#'; } } y++; if(y>n) { y=1; x++; } } } int main() { while(~scanf("%d%d",&n,&k)) { if(n==-1&&k==-1) break; for(int i=1;i<=n;i++) scanf("%s",m[i]+1); ans=0; dfs(1,1,0); printf("%d\n",ans); } return 0; }
B - Dungeon Master
题意:三维走迷宫问题。
思路:BFS,注意边界判断,详见代码。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> using namespace std; const int INF=0x3f3f3f3f; char m[40][40][40]; bool use[40][40][40]; int dirx[6]={0,0,0,0,1,-1}; int diry[6]={0,0,1,-1,0,0}; int dirz[6]={1,-1,0,0,0,0}; int l,r,c,ans; struct node { int x;//r int y;//c int z;//l int num; }s,t; void bfs() { queue<node >q; q.push(s); while(!q.empty()) { node now=q.front(); q.pop(); use[now.x][now.y][now.z]=1; if(now.x==t.x&&now.y==t.y&&now.z==t.z) ans=min(ans,now.num); else for(int i=0;i<6;i++) { if(now.x+dirx[i]<1||now.x+dirx[i]>r) continue; if(now.y+diry[i]<1||now.y+diry[i]>c) continue; if(now.z+dirz[i]<1||now.z+dirz[i]>l) continue; node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.z=now.z+dirz[i]; next.num=now.num+1; if(m[next.x][next.y][next.z]!='#'&&use[next.x][next.y][next.z]==0) { q.push(next); use[next.x][next.y][next.z]=1; } } } } int main() { while(scanf("%d%d%d",&l,&r,&c)!=EOF) { if(l==0&&r==0&&c==0) break; for(int i=1;i<=l;i++) { for(int j=1;j<=r;j++) { getchar(); for(int k=1;k<=c;k++) { scanf("%c",&m[j][k][i]); if(m[j][k][i]=='S') s.x=j,s.y=k,s.z=i,s.num=0; else if(m[j][k][i]=='E') t.x=j,t.y=k,t.z=i; } } getchar(); } memset(use,0,sizeof(use)); ans=INF; bfs(); if(ans==INF) printf("Trapped!\n"); else printf("Escaped in %d minute(s).\n",ans); } return 0; }B
C - Catch That Cow
题意:一维数轴上从n点到k的最短用时。三种移动操作:n+1,n-1,n*2.
思路:BFS问题,从起点开始三个方向进行搜索,注意边界判断,具体看代码。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int INF=0x3f3f3f3f; int use[200100]; struct node { int x; int num; }; int ans; int n,k; int bfs(int nows) { use[nows]=1; queue<node>q; while(!q.empty()) q.pop(); node s; s.x=nows,s.num=0; q.push(s); while(!q.empty()) { node now=q.front(); q.pop(); if(now.x==k) return now.num; if(now.x+1<=100000&&use[now.x+1]==0) { use[now.x+1]=1; node next; next.num=now.num+1; next.x=now.x+1; q.push(next); } if(now.x-1>=0&&now.x-1<=100000&&use[now.x-1]==0) { use[now.x-1]=1; node next; next.num=now.num+1; next.x=now.x-1; q.push(next); } if(now.x*2>=0&&now.x*2<=100000&&use[now.x*2]==0) { use[now.x*2]=1; node next; next.num = now.num + 1; next.x = now.x * 2; q.push(next); } } } int main() { while(~scanf("%d%d",&n,&k)) { memset(use,0,sizeof(use)); ans=bfs(n); printf("%d\n",ans); } return 0; }
D - Fliptile
题意:一个M×N的棋盘,0表示白色,1表示黑色,每次翻转一个棋子及其相邻的棋子。问能否将棋盘翻转为全白。如果可以输出翻转矩阵。
思路:枚举第一行的翻转情况。因为N<=15。最多有2^15次种情况。对每种情况进行搜索,先翻转第一行棋子,然后遍历第二行开始的所有棋子,当前棋子上面的棋子若为黑,则必须翻转当前棋子。
最后判断最后一行是否全白。记录翻转最小次数。具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int m,n;
int dirx[4]={0,0,-1,1};
int diry[4]={1,-1,0,0};
int mp[20][20];
int lsmp[20][20];
int ans[20][20];
int lsans[20][20];
int num,lsnum;
void f(int x,int y) {
lsans[x][y]=1;
lsmp[x][y]=1-lsmp[x][y];
for(int i=0;i<4;i++)
if(x+dirx[i]>=1&&x+dirx[i]<=m&&y+diry[i]>=1&&y+diry[i]<=n)
lsmp[x+dirx[i]][y+diry[i]]=1-lsmp[x+dirx[i]][y+diry[i]];
}
void dfs() {
lsnum=0;
for(int i=1;i<=n;i++)
if(lsans[1][i]==1) {
f(1,i);
lsnum++;
}
for(int i=2;i<=m;i++)
for(int j=1;j<=n;j++)
if(lsmp[i-1][j]==1) {
f(i,j);
lsnum++;
}
int flag=1;
for(int j=1;j<=n;j++)
if(lsmp[m][j]==1) flag=0;
if(flag==1) {
if(lsnum<num) {
num=lsnum;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
ans[i][j]=lsans[i][j];
}
}
}
int main()
{
while(cin>>m>>n) {
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
num=INF;
for(int k=0;k<(1<<(n));k++)
{
memset(lsans,0, sizeof(lsans));
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
lsmp[i][j]=mp[i][j];
for(int j=1;j<=n;j++) {
if(k&(1<<(j-1)))
lsans[1][j]=1;
}
dfs();
}
if(num==INF) printf("IMPOSSIBLE\n");
else
{
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
if (j != n) printf("%d ", ans[i][j]);
else printf("%d\n", ans[i][j]);
}
}
}
}
E - Find The Multiple
题意:中文题,不多说。
思路:首先注意到所有m肯定是一个小的m×10或者m×10+1得到的。那么我们可以从n开始枚举m,直到找到满足要求(m%n==0)的解。实际上最大的m也不会超过long long 。具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
typedef long long int ll;
const int INF=0x3f3f3f3f;
int n;
void bfs()
{
queue<ll> q;
q.push(1);
while(!q.empty())
{
ll now=q.front();
q.pop();
if(now%n==0)
{
cout<<now<<endl;
return ;
}
q.push(now*10);
q.push(now*10+1);
}
}
int main()
{
while(scanf("%d",&n)&&n)
{
bfs();
}
return 0;
}
F - Prime Path
题意:给出四位数的质数n,m。要求每次变换某一位上的数字且每次变换后的数也是质数,求从n到m的最小变换次数。
思路:n和m都只有四位,预处理出质数,直接BFS即可。具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
bool flag[10010];
bool visit[10010];
int t,n,m;
struct node
{
int x;
int step;
};
void init()
{
flag[0]=flag[1]=1;
for(int i=2;i<=10000;i++)
if(flag[i]==0)
{
for(int j=i*2;j<=10000;j+=i)
flag[j]=1;
}
}
int power(int x,int t)
{
int ans=1;
for(int i=1;i<=t;i++)
ans*=x;
return ans;
}
void bfs(int n,int m)
{
memset(visit,0, sizeof(visit));
node now;
visit[n]=1;
now.x=n,now.step=0;
queue<node>q;
q.push(now);
while(!q.empty())
{
node temp=q.front();q.pop();
if(temp.x==m)
{
printf("%d\n",temp.step);
return ;
}
int num[5];
int nowx=temp.x;
num[4]=nowx%10;nowx/=10;
num[3]=nowx%10;nowx/=10;
num[2]=nowx%10;nowx/=10;
num[1]=nowx%10;nowx/=10;
for(int i=1;i<=4;i++)
for(int j=0;j<=9;j++)
{
if(i==1&&j==0) continue;
if(num[i]==j) continue;
if(i==4&&j==0) continue;
int nown=temp.x;
nown=nown-num[i]*power(10,4-i)+j*power(10,4-i);
if(flag[nown]==0&&visit[nown]==0)
{
visit[nown]=1;
node next;
next.x=nown;
next.step=temp.step+1;
q.push(next);
}
}
}
printf("Impossible\n");
}
int main()
{
init();
cin>>t;
while(t--)
{
cin>>n>>m;
if(n==m) cout<<"0"<<endl;
else bfs(n,m);
}
}
G - Shuffle'm Up
题意:给出字符串长度C,两个长度为C的字符串a,b 一个长度为2C的字符串c。每次操作依次轮流从b和a取出字符组成新的字符串d。如果d!=c,将d前半部分给a,后半部分给把,问需要几次操作可以得到C。如果不能输出-1。
思路:虽然放在搜索里,其实是个模拟吧。照着做就行了。注意如果操作次数超过了2C就永远不能组成了。具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
bool flag[10010];
bool visit[10010];
int T,C;
string a,b,c;
int main()
{
cin>>T;
int cases=1;
while(T--)
{
cin>>C;
cin>>a>>b>>c;
if(a+b==c) printf("%d 0\n",cases++);
else
{
int num=0;
int flag=0;
while(num<=2*C)
{
num++;
string d="";
for(int i=0;i<C;i++)
d=d+b[i]+a[i];
if(d==c)
{
flag=1;break;
}
a="";
for(int i=0;i<C;i++)
a+=d[i];
b="";
for(int i=0;i<C;i++)
b+=d[C+i];
}
if(flag==0) printf("%d -1\n",cases++);
else printf("%d %d\n",cases++,num);
}
}
}
H - Pots
题意:有容量为a,b两个容器,问能否通过三种操作(倒满某个容器,倒空某个容器,将一个容器的水倒入另一个容器)得到容量C。输出最小操作数和操作过程或者impossible。
思路:因为a,b<100,直接6方向BFS即可。可以将操作过程在BFS过程同时更新。具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
bool use[110][110];
int aa,bb,cc;
struct caozuo
{
int num;
int from;
int to;
};
struct node
{
int a;
int b;
int step;
vector<caozuo> v;
};
void bfs()
{
//temlist.assign(list.begin(), list.end());
node now;
now.a=0;
now.b=0;
memset(use,0, sizeof(use));
use[0][0]=1;
now.v.clear();
now.step=0;
queue<node >q;
q.push(now);
while(!q.empty())
{
node temp=q.front();q.pop();
if(temp.a==cc||temp.b==cc)
{
printf("%d\n",temp.step);
for(int i=0;i<temp.v.size();i++)
{
caozuo now=temp.v[i];
if(now.num==1)
{
if(now.from==1) printf("FILL(1)\n");
else printf("FILL(2)\n");
}
else if(now.num==2)
{
if(now.from==1) printf("DROP(1)\n");
else printf("DROP(2)\n");
}
else if(now.num==3)
{
if(now.from==1) printf("POUR(1,2)\n");
else printf("POUR(2,1)\n");
}
}
return ;
}
if(temp.a!=aa&&use[aa][temp.b]==0)//a-fill
{
use[aa][temp.b]=1;
node next;
next.a=aa;
next.b=temp.b;
next.step=temp.step+1;
next.v.assign(temp.v.begin(),temp.v.end());
caozuo next1;
next1.num=1;
next1.from=1;
next.v.push_back(next1);
q.push(next);
}
if(temp.b!=bb&&use[temp.a][bb]==0)//b-fill
{
use[temp.a][bb]=1;
node next;
next.a=temp.a;
next.b=bb;
next.step=temp.step+1;
next.v.assign(temp.v.begin(),temp.v.end());
caozuo next1;
next1.num=1;
next1.from=2;
next.v.push_back(next1);
q.push(next);
}
if(temp.a!=0&&use[0][temp.b]==0)//a-0
{
use[0][temp.b]=1;
node next;
next.a=0;
next.b=temp.b;
next.step=temp.step+1;
next.v.assign(temp.v.begin(),temp.v.end());
caozuo next1;
next1.num=2;
next1.from=1;
next.v.push_back(next1);
q.push(next);
}
if(temp.b!=0&&use[temp.a][0]==0)//b-0
{
use[temp.a][0]=1;
node next;
next.a=temp.a;
next.b=0;
next.step=temp.step+1;
next.v.assign(temp.v.begin(),temp.v.end());
caozuo next1;
next1.num=2;
next1.from=2;
next.v.push_back(next1);
q.push(next);
}
if(temp.a!=0&&temp.b!=bb)//a-b
{
if(temp.a+temp.b<=bb&&use[0][temp.a+temp.b]==0) {
use[0][temp.a+temp.b] = 1;
node next;
next.a = 0;
next.b = temp.a+temp.b;
next.step = temp.step + 1;
next.v.assign(temp.v.begin(), temp.v.end());
caozuo next1;
next1.num=3;
next1.from=1;
next1.to=2;
next.v.push_back(next1);
q.push(next);
}
else if(temp.a+temp.b>bb&&use[temp.a+temp.b-bb][bb]==0) {
use[temp.a+temp.b-bb][bb] = 1;
node next;
next.a = temp.a+temp.b-bb;
next.b = bb;
next.step = temp.step + 1;
next.v.assign(temp.v.begin(), temp.v.end());
caozuo next1;
next1.num = 3;
next1.from = 1;
next1.to=2;
next.v.push_back(next1);
q.push(next);
}
}
if(temp.b!=0&&temp.a!=aa)//b-a
{
if(temp.a+temp.b<=aa&&use[temp.a+temp.b][0]==0) {
use[temp.a+temp.b][0] = 1;
node next;
next.a = temp.a+temp.b;
next.b = 0;
next.step = temp.step + 1;
next.v.assign(temp.v.begin(), temp.v.end());
caozuo next1;
next1.num=3;
next1.from=2;
next1.to=1;
next.v.push_back(next1);
q.push(next);
}
else if(temp.a+temp.b>aa&&use[aa][temp.a+temp.b-aa]==0) {
use[aa][temp.a+temp.b-aa] = 1;
node next;
next.a = aa;
next.b = temp.a+temp.b-aa;
next.step = temp.step + 1;
next.v.assign(temp.v.begin(), temp.v.end());
caozuo next1;
next1.num=3;
next1.from=2;
next1.to=1;
next.v.push_back(next1);
q.push(next);
}
}
}
printf("impossible\n");
}
int main()
{
while(cin>>aa>>bb>>cc)
{
bfs();
}
}
I - Fire Game(http://acm.fzu.edu.cn/problem.php?pid=2150)
题意:'#'可以燃烧,'.'不可以燃烧。选择两个#点(可以重复)放火,每过一秒可以向四个方向燃烧,问能否全部烧光所有的#,如果可以给出烧光的最少时间。
思路:注意到数据规模很小,我们可以暴力枚举两个#点。初始化到达每个#的时间为INF。做两遍BFS,到达每个#的时间为两遍BFS里短的时间。每一种情况所需的时间为所有#的最长到达时间。最后取所有最长时间的最小值。具体看代码。可以用双向BFS优化为一次BFS。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; int m,n; int dirx[4]={0,0,-1,1}; int diry[4]={1,-1,0,0}; char mp[15][15]; int lsans[15][15],ans; struct node { int x; int y; int step; }; bool use[15][15]; void bfs(int xx,int yy) { memset(use,0,sizeof(use)); queue<node >q; node now; now.x=xx,now.y=yy,now.step=0; use[xx][yy]=1; q.push(now); while(!q.empty()) { node now=q.front(); lsans[now.x][now.y]=min( lsans[now.x][now.y],now.step); q.pop(); for(int i=0;i<4;i++) { node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.step=now.step+1; if(use[next.x][next.y]==1) continue; if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m) if(mp[next.x][next.y]=='#') { use[next.x][next.y]=1; q.push(next); } } } } int main() { int t; int cas=1; scanf("%d",&t); while(t--) { ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='#') ans=INF; for(int i=1;i<=n*m;i++) { int nx=i/m+1,ny=i%m; if(ny==0) nx--,ny=m; if(mp[nx][ny]!='#') continue; for(int j=i;j<=n*m;j++) { int nnx=j/m+1,nny=j%m; if(nny==0) nnx--,nny=m; if(mp[nnx][nny]=='#') { memset(lsans,INF,sizeof(lsans)); bfs(nx,ny); bfs(nnx,nny); int lsnum=0; for(int k=1;k<=n;k++) for(int p=1;p<=m;p++) if(mp[k][p]=='#') lsnum=max(lsnum,lsans[k][p]); ans=min(ans,lsnum); } } } if(ans!=INF) printf("Case %d: %d\n",cas++,ans); else printf("Case %d: -1\n",cas++); } }
J - Fire!
题意:F的位置是火,J的位置是人。询问人是否可以逃出迷宫,如果可以求逃出迷宫的时间。注意起火点不一定只有一个。
思路:先做一次BFS求出每个点的起火时间,再做一遍BFS判断能否逃出。具体看代码。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=1010; int n,m; struct node { char p; int fire; int peo; int x; int y; }mp[MAXN][MAXN]; int jx,jy,ans; bool use[1010][1010]; int dirx[4]={0,0,1,-1}; int diry[4]={1,-1,0,0}; void dfs1() { queue<node >q; memset(use,0, sizeof(use)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(mp[i][j].p=='F') { mp[i][j].fire=0; q.push(mp[i][j]); } } while(!q.empty()) { node now=q.front(); q.pop(); for(int i=0;i<4;i++) { if(now.x+dirx[i]>=1&&now.x+dirx[i]<=n&&now.y+diry[i]>=1&&now.y+diry[i]<=m) if(use[now.x+dirx[i]][now.y+diry[i]]==0) if(mp[now.x+dirx[i]][now.y+diry[i]].p=='.') { use[now.x+dirx[i]][now.y+diry[i]]=1; mp[now.x+dirx[i]][now.y+diry[i]].fire=now.fire+1; q.push(mp[now.x+dirx[i]][now.y+diry[i]]); } } } } void dfs2() { mp[jx][jy].peo=0; queue<node >q; q.push(mp[jx][jy]); memset(use,0, sizeof(use)); use[jx][jy]=1; while(!q.empty()) { node now=q.front(); q.pop(); if(now.x==0||now.x==n+1||now.y==0||now.y==m+1) ans=min(ans,now.peo); for(int i=0;i<4;i++) { if(now.x+dirx[i]>=0&&now.x+dirx[i]<=n+1&&now.y+diry[i]>=0&&now.y+diry[i]<=m+1) if(use[now.x+dirx[i]][now.y+diry[i]]==0) if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||mp[now.x+dirx[i]][now.y+diry[i]].p=='.') if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||now.peo+1<mp[now.x+dirx[i]][now.y+diry[i]].fire) { use[now.x+dirx[i]][now.y+diry[i]]=1; mp[now.x+dirx[i]][now.y+diry[i]].peo=now.peo+1; q.push(mp[now.x+dirx[i]][now.y+diry[i]]); } } } } int main() { int t; int cas=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { getchar(); for(int j=1;j<=m;j++) { scanf("%c",&mp[i][j].p); if(mp[i][j].p=='J') { jx=i; jy=j; } } } for(int i=0;i<=n+1;i++) for(int j=0;j<=m+1;j++) mp[i][j].x=i,mp[i][j].y=j,mp[i][j].peo=mp[i][j].fire=INF; ans=INF; dfs1(); dfs2(); if(ans!=INF) cout<<ans<<endl; else cout<<"IMPOSSIBLE"<<endl; } }
K - 迷宫问题
题意:5×5的地图,0可以走,1不可以走。求从左上角走到有右下角的唯一最短路径。要求输出路径。
思路:BFS。路径可以保存在每一次的状态里。具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
int visit[10][10];
int mp[10][10];
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
struct road
{
int x;
int y;
};
struct node
{
int nx;
int ny;
vector<road>v;
};
void bfs()
{
node now;
road now1;
now1.x=1,now1.y=1;
now.v.push_back(now1);
now.nx=1,now.ny=1;
memset(visit,0, sizeof(visit));
visit[1][1]=1;
queue<node >q;
q.push(now);
while(!q.empty())
{
node temp=q.front();
q.pop();
if(temp.nx==5&&temp.ny==5)
{
int num=temp.v.size();
for(int i=0;i<num;i++)
{
printf("(%d, %d)\n",temp.v[i].x-1,temp.v[i].y-1);
}
return ;
}
for(int i=0;i<4;i++)
{
node next;
next.nx=temp.nx+dirx[i];
next.ny=temp.ny+diry[i];
next.v.assign(temp.v.begin(),temp.v.end());
road next1;
next1.x=next.nx;
next1.y=next.ny;
next.v.push_back(next1);
if(next.nx>=1&&next.nx<=5&&next.ny>=1&&next.ny<=5)
if(visit[next.nx][next.ny]==0&&mp[next.nx][next.ny]==0)
{
visit[next.nx][next.ny]=1;
q.push(next);
}
}
}
}
int main()
{
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
cin>>mp[i][j];
bfs();
}
L - Oil Deposits
题意:求联通块数,注意斜对角也算联通。
思路:DFS 每次选择'@'点,将与之联通的设为'.',DFS的次数就是联通块数。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=110;
int n,m;
char mp[MAXN][MAXN];
int dirx[8]={1,-1,0,0,1,1,-1,-1};
int diry[8]={0,0,1,-1,1,-1,1,-1};
int ans;
void dfs(int x,int y)
{
mp[x][y]='*';
for(int i=0;i<8;i++)
{
int nx=x+dirx[i];
int ny=y+diry[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]=='@') dfs(nx,ny);
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
for(int i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
}
ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]=='@')
{
ans++;
dfs(i,j);
}
printf("%d\n",ans);
}
}
M - 非常可乐(HDOJ1495)
题意:给你一瓶容量为S的可乐和两个容量分别为N、M的杯子。询问最少能平分可乐的次数。如果不能输出NO。
思路:可以看成是一个有六个方向的BFS。六个方向:s->n,s->m,n->s,n->m,n->m,m->n 具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int nn,mm,ss;
bool use[110][110];
struct node
{
int n;
int m;
int s;
int t;
};
int bfs()
{
node now;
now.n=0,now.m=0,now.s=ss,now.t=0;
memset(use,0,sizeof(use));
use[0][0]=1;
queue<node>q;
q.push(now);
while(!q.empty())
{
node now=q.front();
q.pop();
if(now.n==ss/2&&now.s==ss/2) return now.t;
if(now.n<nn)//s->n
{
int nextn=nn;
int nextm=now.m;
int nexts=now.n+now.s-nn;
if(use[nextn][nextm]==0)
{
use[nextn][nextm]=1;
node next;
next.m=nextm;
next.n=nextn;
next.s=nexts;
next.t=now.t+1;
q.push(next);
}
}
if(now.m<mm)//s->m
{
int nextn=now.n;
int nextm=mm;
int nexts=now.m+now.s-mm;
if(use[nextn][nextm]==0)
{
use[nextn][nextm]=1;
node next;
next.m=nextm;
next.n=nextn;
next.s=nexts;
next.t=now.t+1;
q.push(next);
}
}
if(now.n>0)//n->s
{
int nextn=0;
int nextm=now.m;
int nexts=now.n+now.s;
if(use[nextn][nextm]==0)
{
use[nextn][nextm]=1;
node next;
next.m=nextm;
next.n=nextn;
next.s=nexts;
next.t=now.t+1;
q.push(next);
}
}
if(now.m>0)//m->s
{
int nextn=now.n;
int nextm=0;
int nexts=now.m+now.s;
if(use[nextn][nextm]==0)
{
use[nextn][nextm]=1;
node next;
next.m=nextm;
next.n=nextn;
next.s=nexts;
next.t=now.t+1;
q.push(next);
}
}
if(now.m>0&&now.n<nn)//m->n
{
int nextn,nextm,nexts;
if(now.m+now.n<=nn)
{
nextm=0;
nextn=now.m+now.n;
nexts=now.s;
}
else
{
nextm=now.m+now.n-nn;
nextn=nn;
nexts=now.s;
}
if(use[nextn][nextm]==0)
{
use[nextn][nextm]=1;
node next;
next.m=nextm;
next.n=nextn;
next.s=nexts;
next.t=now.t+1;
q.push(next);
}
}
if(now.n>0&&now.m<mm)//n->m
{
int nextn,nextm,nexts;
if(now.n+now.m<=mm)
{
nextm=now.m+now.n;
nextn=0;
nexts=now.s;
}
else
{
nextm=mm;
nextn=now.n+now.m-mm;
nexts=now.s;
}
if(use[nextn][nextm]==0)
{
use[nextn][nextm]=1;
node next;
next.m=nextm;
next.n=nextn;
next.s=nexts;
next.t=now.t+1;
q.push(next);
}
}
}
return 0;
}
int main()
{
while(~scanf("%d%d%d",&ss,&nn,&mm))
{
if(nn==0&&mm==0&&ss==0) break;
if(nn<mm) swap(nn,mm);
if(ss%2==1)
printf("NO\n");
else
{
int ans=bfs();
if(ans==0) printf("NO\n");
else printf("%d\n",ans);
}
}
}
N - Find a way(HDOJ2612)
题意:求两个人到所有KFC的时间和的最小值。
思路:2次BFS求出两个人分别到每个KFC的时间。最后选择和的最小值。具体看代码。
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m;
char mp[210][210];
bool use[210][210];
int ans1[210][210];
int ans2[210][210];
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
struct node
{
int x;
int y;
int t;
};
void bfs1()
{
memset(use,0,sizeof(use));
memset(ans1,INF,sizeof(ans1));
node now;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]=='Y')
{
now.x=i;
now.y=j;
break;
}
now.t=0;
use[now.x][now.y]=1;
queue<node >q;
q.push(now);
while(!q.empty())
{
node now=q.front();
if(mp[now.x][now.y]=='@')
ans1[now.x][now.y]=now.t;
q.pop();
for(int i=0;i<4;i++)
{
node next;
next.x=now.x+dirx[i];
next.y=now.y+diry[i];
next.t=now.t+1;
if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m)
if(mp[next.x][next.y]!='#')
if(use[next.x][next.y]==0)
{
use[next.x][next.y]=1;
q.push(next);
}
}
}
}
void bfs2()
{
memset(use,0, sizeof(use));
memset(ans2,INF,sizeof(ans2));
node now;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]=='M')
{
now.x=i;
now.y=j;
break;
}
now.t=0;
use[now.x][now.y]=1;
queue<node >q;
q.push(now);
while(!q.empty())
{
node now=q.front();
if(mp[now.x][now.y]=='@')
ans2[now.x][now.y]=now.t;
q.pop();
for(int i=0;i<4;i++)
{
node next;
next.x=now.x+dirx[i];
next.y=now.y+diry[i];
next.t=now.t+1;
if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m)
if(mp[next.x][next.y]!='#')
if(use[next.x][next.y]==0)
{
use[next.x][next.y]=1;
q.push(next);
}
}
}
}
void solve()
{
int ans=INF;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]=='@')
ans=min(ans,ans1[i][j]+ans2[i][j]);
printf("%d\n",ans*11);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
bfs1();
bfs2();
solve();
}
}