hdu 1026 Ignatius and the Princess I
需要记录路径,别的地方就没什么难的了。
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 105
int mark[N][N],vis[N][N];
int n,m;
char s[N];
int cnt;
int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
struct node
{
int x,y;
int cnt;
friend bool operator<(node a,node b)
{
return a.cnt>b.cnt;
};
}q[N*N];
struct point
{
int prex,prey;
}ans[N][N];
int judge(int x,int y)
{
if(x>=1&&x<=m&&y>=1&&y<=n&&mark[x][y]!=-1&&vis[x][y]==0) return 1;
return 0;
}
int BFS()
{
node cur,next;
cur.x=1;cur.y=1;cur.cnt=0;vis[1][1]=1;
priority_queue<node>q;
q.push(cur);
while(!q.empty())
{
cur=q.top();
q.pop();
for(int i=0;i<4;i++)
{
next.cnt=cur.cnt+1;
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(judge(next.x,next.y))
{
if(mark[next.x][next.y]!=0) next.cnt+=mark[next.x][next.y];
vis[next.x][next.y]=1;
ans[next.x][next.y].prex=cur.x;ans[next.x][next.y].prey=cur.y;
if(next.x==m&&next.y==n) return next.cnt;
q.push(next);
}
}
}
return -1;
}
void print(int x,int y)
{
if(x==1&&y==1) return ;
print(ans[x][y].prex,ans[x][y].prey);
printf("%ds:(%d,%d)->(%d,%d)\n",cnt++,ans[x][y].prex-1,ans[x][y].prey-1,x-1,y-1);
if(mark[x][y]==0) return ;
while(mark[x][y]--) printf("%ds:FIGHT AT (%d,%d)\n",cnt++,x-1,y-1);
return ;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
getchar();
for(int i=1;i<=m;i++)
{
gets(s+1);
for(int j=1;j<=n;j++)
{
if(s[j]=='.') mark[i][j]=0;
else if(s[j]=='X') mark[i][j]=-1;
else mark[i][j]=s[j]-'0';
}
}
int answer;
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
answer=BFS();
if(answer==-1) printf("God please help our poor hero.\n");
else
{
printf("It takes %d seconds to reach the target position, let me show you the way.\n",answer);
cnt=1;
print(m,n);
}
printf("FINISH\n");
}
return 0;
}
hdu 3316 Mine sweeping
做这道题的时候犯了三个错误,一道不难的题结果wa了很多次才A掉。
一、将ans数组的初值设为0,但是在输出的时候如果ans[i][j]为0,就输出‘".",这个很二。
二、每次搜索一个点的时候,应该对它周围八个点进行检查,我还是习惯性的检查了四个点。
三、忘了在输出"it is a beiju!"后面双换行,这个错误贡献了很多个PE。
思路很直白,对于搜到的每一个点检查周围是否有地雷,如果有的话,记录地雷的数量,并且不对当前的点进行搜索,否则对当前点开始搜索。
#include<stdio.h>
#include<string.h>
#define N 105
int mark[N][N],vis[N][N],ans[N][N];
int dir[8][2]={{1,0},{0,1},{-1,0},{0,-1},{-1,-1},{-1,1},{1,-1},{1,1}};
int n,x,y;
char s[N];
struct node
{
int x,y;
}q[N*N];
int fun(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=n) return 1;
return 0;
}
int judge(int x,int y)
{
int sum=0;
if(fun(x-1,y-1)&&mark[x-1][y-1]==-1) sum++;
if(fun(x-1,y)&&mark[x-1][y]==-1) sum++;
if(fun(x-1,y+1)&&mark[x-1][y+1]==-1) sum++;
if(fun(x,y-1)&&mark[x][y-1]==-1) sum++;
if(fun(x,y+1)&&mark[x][y+1]==-1) sum++;
if(fun(x+1,y-1)&&mark[x+1][y-1]==-1) sum++;
if(fun(x+1,y)&&mark[x+1][y]==-1) sum++;
if(fun(x+1,y+1)&&mark[x+1][y+1]==-1) sum++;
return sum;
}
void BFS()
{
node cur,next;
int head,tail;
head=tail=0;
cur.x=x;cur.y=y;
vis[cur.x][cur.y]=1;
q[tail++]=cur;
while(head!=tail)
{
cur=q[head++];
ans[cur.x][cur.y]=judge(cur.x,cur.y);
if(ans[cur.x][cur.y]!=0) continue;
for(int i=0;i<8;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(fun(next.x,next.y)&&vis[next.x][next.y]==0)
{
vis[next.x][next.y]=1;
q[tail++]=next;
}
}
}
return ;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
getchar();
for(int i=1;i<=n;i++)
{
gets(s+1);
for(int j=1;j<=n;j++)
{
if(s[j]=='O') mark[i][j]=0;
else if(s[j]=='X') mark[i][j]=-1;
}
}
scanf("%d%d",&x,&y);
x++;y++;
if(mark[x][y]==-1)
{
printf("it is a beiju!\n\n");
continue;
}
memset(vis,0,sizeof(vis));
memset(ans,-1,sizeof(ans));
BFS();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(ans[i][j]==-1) printf(".");
else printf("%d",ans[i][j]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
hdu 4308 Saving Princess claire_
这道题主要有两个问题。
一、解决内存大小的问题,这道题需要动态申请内存,如果直接开一个5000*5000的内存,会MLE。
二、题目数据有问题,我记录的cost用int提交wa,改为long long提交之后AC。但是题目保证最多5000个节点,每个节点的花费不超过10000,理论上最大花费是5*10^7,不会超int。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
using namespace std;
#define N 5005
typedef long long LL;
int n,m,k,cnt;
int **mark,**vis;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int sx,sy;
char s[N];
struct node
{
int x,y;
LL cost;
friend bool operator<(node a,node b)
{
return a.cost>b.cost;
};
};
struct point
{
int x,y;
}hash[N];
int judge(int x,int y)
{
if(x<1||x>m||y<1||y>n) return 0;
if(vis[x][y]==1) return 0;
if(mark[x][y]==-1) return 0;
return 1;
}
LL BFS()
{
node cur,next;
priority_queue<node>q;
cur.x=sx;cur.y=sy;cur.cost=0;
vis[cur.x][cur.y]=1;
q.push(cur);
while(!q.empty())
{
cur=q.top();
q.pop();
for(int i=0;i<4;i++)
{
next.cost=cur.cost;
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(judge(next.x,next.y))
{
if(mark[next.x][next.y]==1) next.cost=cur.cost+k;
vis[next.x][next.y]=1;
if(mark[next.x][next.y]==2) return next.cost;
q.push(next);
}
}
if(mark[cur.x][cur.y]==10)
{
for(int i=0;i<cnt;i++)
{
next.x=hash[i].x;
next.y=hash[i].y;
next.cost=cur.cost;
if(judge(hash[i].x,hash[i].y))
{
vis[hash[i].x][hash[i].y]=1;
q.push(next);
}
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d%d",&m,&n,&k)!=EOF)
{
getchar();
mark=(int **)malloc((m+2)*sizeof(int *));
for(int i=0;i<=m+1;i++) mark[i]=(int *)malloc((n+2)*sizeof(int));
vis=(int **)malloc((m+2)*sizeof(int *));
for(int i=0;i<=m+1;i++) vis[i]=(int *)malloc((n+2)*sizeof(int));
cnt=0;
for(int i=1;i<=m;i++)
{
gets(s+1);
for(int j=1;j<=n;j++)
{
if(s[j]=='Y')
{
mark[i][j]=0;
sx=i;
sy=j;
}
else if(s[j]=='C') mark[i][j]=2;
else if(s[j]=='#') mark[i][j]=-1;
else if(s[j]=='*') mark[i][j]=1;
else if(s[j]=='P')
{
mark[i][j]=10;
hash[cnt].x=i;hash[cnt].y=j;cnt++;
}
}
}
LL ans;
memset(vis,0,sizeof(vis));
ans=BFS();
if(ans==-1) printf("Damn teoy!\n");
else printf("%I64d\n",ans);
}
return 0;
}
hdu 2216 Game III
这道题错了很多遍,主要错在两个地方。
一、不能用scanf("%c",&c)读入,这个是题目的原因,之前遇到过几次这个问题,很烦!
二、我特么的没有对vis初始化!
题目思路倒是很简单,一个人的状态不好记录,两个人放一块儿就很容易记录了。
#include<stdio.h>
#include<string.h>
#define N 25
int mark[N][N],vis[N][N][N][N];
int m,n;
int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}};
char s[N][N];
struct node
{
int x1,y1;
int x2,y2;
int cnt;
}q[500000],a;
int abs(int x)
{
if(x<0) return -x;
return x;
}
int fun(node a)
{
int temp=abs(a.x1-a.x2)+abs(a.y1-a.y2);
if(temp==1||temp==0) return 1;
return 0;
}
int judge(int x,int y)
{
if(x<1||x>m||y<1||y>n) return 0;
if(mark[x][y]==-1) return 0;
return 1;
}
int BFS()
{
node cur,next;
cur=a;
vis[a.x1][a.y1][a.x2][a.y2]=1;
if(fun(a)) return 0;
int head,tail;
head=tail=0;
q[tail++]=cur;
while(head!=tail)
{
cur=q[head++];
next.cnt=cur.cnt+1;
for(int i=0;i<4;i++)
{
next.x1=cur.x1+dir[i][0];
next.y1=cur.y1+dir[i][1];
if(judge(next.x1,next.y1))
{
next.x2=cur.x2+dir[3-i][0];
next.y2=cur.y2+dir[3-i][1];
if(!judge(next.x2,next.y2))
{
next.x2=cur.x2;
next.y2=cur.y2;
}
if(vis[next.x1][next.y1][next.x2][next.y2]==1) continue;
if(fun(next)) return next.cnt;
q[tail++]=next;
vis[next.x1][next.y1][next.x2][next.y2]=1;
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
getchar();
for(int i=1;i<=m;i++) gets(s[i]+1);
a.cnt=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
char c;
c=s[i][j];
if(c=='.') mark[i][j]=0;
else if(c=='X') mark[i][j]=-1;
else if(c=='Z')
{
mark[i][j]=0;
a.x1=i;a.y1=j;
}
else if(c=='S')
{
mark[i][j]=0;
a.x2=i;a.y2=j;
}
}
}
int ans;
memset(vis,0,sizeof(vis));
ans=BFS();
if(ans==-1) printf("Bad Luck!\n");
else printf("%d\n",ans);
}
return 0;
}
hdu 2531 Catch him
很好玩儿的一道题。
题目读完,麻烦的地方时怎么记录状态,开始的时候我没理解题目的意思,以为题目保证每个球员的是矩形,提交wa了两边之后重新读题才发现是一个二维的图形,什么图形都可以。所以干脆用一个数组记录状态,反正一个球员最多只占二十格,然后对于其中最小的点来标记是否到达过,之后就是普通的广搜了。
#include<stdio.h>
#include<string.h>
#define N 105
int mark[N][N],vis[N][N];
int s,e,m,n,k;
int minx,miny;
int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
struct point
{
int x,y;
}a[21];
struct node
{
int x,y;
int cnt;
point hash[21];
}q[N*N];
int judge(int x,int y)
{
if(x<1||x>m) return -1;
if(y<1||y>n) return -1;
if(mark[x][y]==1) return 1;
if(mark[x][y]==-1) return -1;
return 0;
}
int BFS()
{
int head,tail;
node cur,next;
head=tail=0;
cur.x=minx;cur.y=miny;cur.cnt=0;
for(int i=0;i<k;i++) cur.hash[i].x=a[i].x,cur.hash[i].y=a[i].y;
vis[cur.x][cur.y]=1;
q[tail++]=cur;
while(head!=tail)
{
cur=q[head++];
next.cnt=cur.cnt+1;
for(int i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
int flag=0;
for(int j=0;j<k;j++)
{
next.hash[j].x=cur.hash[j].x+dir[i][0];
next.hash[j].y=cur.hash[j].y+dir[i][1];
int ans=judge(next.hash[j].x,next.hash[j].y);
if(ans==-1)
{
flag=-1;
break;
}
else if(ans==1) flag=1;
}
if(flag==-1) continue;
if(vis[next.x][next.y]==1) continue;
if(flag==1) return next.cnt;
q[tail++]=next;vis[next.x][next.y]=1;
}
}
return -1;
}
int main()
{
while(scanf("%d%d",&m,&n),m+n)
{
getchar();
k=0;
minx=m+1;miny=n+1;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
char c;
scanf("%c",&c);
if(c=='.') mark[i][j]=0;
else if(c=='Q') mark[i][j]=1;
else if(c=='O') mark[i][j]=-1;
else
{
mark[i][j]=0;
a[k].x=i;a[k].y=j;k++;
if(i<minx) minx=i;
if(j<miny) miny=j;
}
}
getchar();
}
int ans;
memset(vis,0,sizeof(vis));
ans=BFS();
if(ans==-1) printf("Impossible\n");
else printf("%d\n",ans);
}
return 0;
}
hdu 2209 翻纸牌游戏
看到题目的瞬间就想到了将所有纸牌的状态用二进制表示出来,20张牌刚好有大概一百万种状态,一百万种,从刚开始学BFS搜迷宫开始,差不多是我遇到的BFS里最经常碰见的状态数量了。
通过位运算来实现状态的转移,然后搜索所有的状态,最快搜索到的就是结果,如果搜索完所有能到达的状态仍然没有到达目标状态的时候,输出NO
#include<stdio.h>
#include<string.h>
#define N 25
char s[N];
int n;
int start,end;
int vis[(1<<20)+1];
struct node
{
int x,cnt;
}q[(1<<N)+1];
int BFS()
{
node cur,next;
cur.x=start;
cur.cnt=0;
vis[start]=1;
int head,tail;
head=tail=0;
q[tail++]=cur;
while(head!=tail)
{
cur=q[head++];
int temp=1;
next.cnt=cur.cnt+1;
for(int i=0;i<n;i++)
{
if(i<2) temp=(temp<<1)+1;
else temp<<=1;
if(i==n-1) temp&=(temp>>1);
next.x=cur.x^temp;
if(next.x==end) return next.cnt;
if(vis[next.x]==0)
{
q[tail++]=next;
vis[next.x]=1;
}
}
}
return -1;
}
int main()
{
while(gets(s))
{
n=strlen(s);
start=0;end=0;
for(int i=0;i<n;i++) start=start*2+s[i]-'0';
if(start==end)
{
printf("0\n");
continue;
}
if(n==1&&start!=end)
{
printf("1\n");
continue;
}
int ans;
memset(vis,0,sizeof(vis));
ans=BFS();
if(ans==-1) printf("NO\n");
else printf("%d\n",ans);
}
return 0;
}
hdu 4771 Stealing Harry Potter's Precious
用二进制来记录不同的宝物。
#include<stdio.h>
#include<string.h>
#include<queue>
#define N 105
using namespace std;
int vis[N][N][16],mark[N][N];
int n,m,k;
int sx,sy;
int dir[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
int temp;
struct node
{
int x,y,k;
int cnt;
};
int judge(int x,int y)
{
if(x>=1&&x<=m&&y>=1&&y<=n&&mark[x][y]!=-1) return 1;
return 0;
}
int bfs()
{
queue<node>q;
node cur,next;
cur.x=sx;
cur.y=sy;
cur.cnt=0;
if(mark[sx][sy]==2)
{
// mark[sx][sy]=1;
cur.k=1;
}
else cur.k=0;
vis[cur.x][cur.y][cur.k]=1;
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
for(int i=0; i<4; i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.cnt=cur.cnt+1;
if(judge(next.x,next.y))
{
if(mark[next.x][next.y]>=1&&(mark[next.x][next.y]&cur.k)==0)
{
next.k=cur.k+mark[next.x][next.y];
//mark[next.x][next.y]=1;
}
else next.k=cur.k;
if(vis[next.x][next.y][next.k]==0)
{
vis[next.x][next.y][next.k]=1;
if(next.k==temp-1) return next.cnt;
q.push(next);
}
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d",&m,&n),n+m)
{
getchar();
memset(mark,0,sizeof(mark));
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
char c;
scanf("%c",&c);
if(c=='#') mark[i][j]=-1;
else if(c=='.') mark[i][j]=0;
else if(c=='@')
{
mark[i][j]=0;
sx=i;
sy=j;
}
}
getchar();
}
scanf("%d",&k);
temp=1;
for(int i=1; i<=k; i++)
{
int x,y;
scanf("%d%d",&x,&y);
mark[x][y]=temp;
temp*=2;
}
memset(vis,0,sizeof(vis));
int ans;
ans=bfs();
printf("%d\n",ans);
}
return 0;
}
hdu 2579 Dating with girls(2)
两种解法吧。自己的思路:如果面对一面墙,并不是不能进入这面墙,而是要等一段儿时间,这段时间不能站在原地不动,还要四处转转。所以要检查能不能四处转转。如果能,并且这面墙还有k(k必须是奇数)段时间才能降下去,就可以进入,否则不能进入。并且不能从墙走到墙。为了每次输出时间最短的点,用优先队列维护。
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 105
int mark[N][N],vis[N][N];
int sx,sy,ex,ey;
int m,n,k;
struct node
{
int x,y;
int cnt;
int flag;
friend bool operator<(node a,node b)
{
return a.cnt>b.cnt;
};
};
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int judge(int x,int y,int t)
{
if(x>=1&&x<=m&&y>=1&&y<=n&&vis[x][y]==0)
return 1;
return 0;
}
int f(int x,int y)
{
if(x>=1&&x<=m&&y>=1&&y<=n&&mark[x][y]==1)
return 1;
return 0;
}
int Find(int x,int y)
{
int tx,ty;
for(int i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(f(tx,ty)) return 1;
}
return 0;
}
int bfs()
{
priority_queue<node>q;
node cur,next;
cur.x=sx;cur.y=sy;cur.cnt=0;cur.flag=1;
vis[sx][sy]=1;
q.push(cur);
while(!q.empty())
{
cur=q.top();
if(cur.x==ex&&cur.y==ey) return cur.cnt;
q.pop();
for(int i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.cnt=cur.cnt+1;
if(judge(next.x,next.y,next.cnt))
{
if(mark[next.x][next.y]==1)
;
else if(mark[next.x][next.y]==2)
{
if(cur.flag==2) continue;
if(next.cnt%k!=0)
{
int temp;
temp=cur.cnt%k;
temp=k-temp;
if(!Find(cur.x,cur.y)) continue;
if(cur.flag==2) continue;
if(temp%2==1) next.cnt=cur.cnt+temp;
else continue;
}
}
vis[next.x][next.y]=1;
next.flag=mark[next.x][next.y];
q.push(next);
}
}
}
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&m,&n,&k);
getchar();
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
char c;
scanf("%c",&c);
if(c=='.') mark[i][j]=1;
else if(c=='#') mark[i][j]=2;
else if(c=='Y')
{
mark[i][j]=1;
sx=i;sy=j;
}
else if(c=='G')
{
mark[i][j]=1;
ex=i;ey=j;
}
}
getchar();
}
int ans;
memset(vis,0,sizeof(vis));
ans=bfs();
if(ans==-1) printf("Please give me another chance!\n");
else printf("%d\n",ans);
}
return 0;
}
网上比较流行的思路:同一个点可以走多次,但是最多不能超过k次。在二维的基础上扩展一维,将二维的搜索转化为三维。
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 105
int vis[N][N][12],mark[N][N];
int n,m,k;
int sx,sy,ex,ey;
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
struct node
{
int x,y;
int cnt;
};
int judge(int x,int y,int t)
{
if(x>=1&&x<=m&&y>=1&&y<=n&&t>=0&&t<=10&&vis[x][y][t]==0)
{
if(mark[x][y]==1) return 1;
else if(mark[x][y]==2&&t==0) return 1;
}
return 0;
}
int bfs()
{
queue<node>q;
node cur,next;
cur.x=sx;cur.y=sy;cur.cnt=0;
vis[sx][sy][0]=1;
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
for(int i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.cnt=cur.cnt+1;
if(judge(next.x,next.y,next.cnt%k))
{
vis[next.x][next.y][next.cnt%k]=1;
if(next.x==ex&&next.y==ey) return next.cnt;
q.push(next);
}
}
}
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&m,&n,&k);
getchar();
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
char c;
scanf("%c",&c);
if(c=='.') mark[i][j]=1;
else if(c=='#') mark[i][j]=2;
else if(c=='Y')
{
mark[i][j]=1;
sx=i;sy=j;
}
else if(c=='G')
{
mark[i][j]=1;
ex=i;ey=j;
}
}
getchar();
}
memset(vis,0,sizeof(vis));
int ans=bfs();
if(ans==-1) printf("Please give me another chance!\n");
else printf("%d\n",ans);
}
return 0;
}
hdu 4474 Yet Another Multiple Problem
对于一个数k,我们想知道给它加一个尾数a,即k*10+a能不能被n整除,我们没必要去记录k,我们需要记录的只是k%n的值,因为k%n*10+a能被10整除,那么k*10+a就一定能被10整除。而对于v(k%10),我们只能允许它入队一次。假如它可以入队多次,就会形成环。比如pre[5]=7,pre[7]=5,pre[5]=7……这样的话,我们就把需要搜索的点缩小到了1~n一共n个点,而n范围是1~10000,这么几个点搜完真是太随意了。
输出结果的时候卡我了一下,想了好久,用了一种很笨的方法输出了结果。看了看别人的输出方法,就是多开一个数组,瞬间代码就变得简单了许多。。。。
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 100005
int mark[15],pre[N],q[N];
int n,m;
void print(int x)
{
if(x==0) return ;
print(pre[x]);
for(int i=0; i<10; i++)
{
if(mark[i]!=1&&(pre[x]*10+i)%n==x)
{
printf("%d",i);
break;
}
}
return ;
}
void BFS()
{
int head,tail;
head=tail=0;
int t=n;
int flag=0;
while(t)
{
if(mark[t%10]==1)
{
flag=1;
break;
}
t/=10;
}
if(!flag)
{
printf("%d\n",n);
return ;
}
q[tail++]=0;
pre[0]=0;
while(head<tail)
{
int cur;
cur=q[head++];
for(int i=0; i<=9; i++)
{
if(mark[i]!=1)
{
int x;
x=cur*10+i;
if(x==0) continue;
if(x%n==0)
{
print(cur);
printf("%d\n",i);
return ;
}
int v;
v=x%n;
if(pre[v]==-1)
{
q[tail++]=v;
pre[v]=cur;
}
}
}
}
printf("-1\n");
return ;
}
int main()
{
int cnt=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(mark,0,sizeof(mark));
for(int i=0; i<m; i++)
{
int x;
scanf("%d",&x);
mark[x]=1;
}
memset(pre,-1,sizeof(pre));
printf("Case %d: ",cnt++);
BFS();
}
return 0;
}
hdu 3713 Double Maze
这道题两个maze分开看的话每个点都可以到达多次,但是如果两个maze放在一块儿,将他们两个的状态作为一个状态来记录,那么这个状态就只能到达一次。比如说对于第一个maze中的1,3这个点和第二个maze中的2,4这个点,这两个点都可以到达很多次,但是第一个maze在1,3,同时第二个maze在2,4这种状态却只允许出现一次。这样这道题就变成了一个有6^4种状态的迷宫,看最快需要多久才能到达终点状态,并且输出字典序最小的。
将两个出发点放在一块儿当作起始状态,两个终点放在一块儿当作终点状态,做一次bfs,在每一个状态记录它的前驱状态。将四个方向按照字典序排序,这样搜索到的第一个终点就是字典序最小的方案,然后递归输出方案。
没有注意起点和终点可以是同一点,wa了许久。。。。
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 8
int mark[N][N][N][N];
int a[N][N],b[N][N];
int ans[10005];
int dir[4][4]= {{1,0,1,0},{0,-1,0,-1},{0,1,0,1},{-1,0,-1,0}};
int flag[4]= {2,1,4,8};
char s[4]= {'D','L','R','U'};
struct node
{
int x,y;
int xx,yy;
int x1,y1,x2,y2;
} sa,sb,ea,eb,vis[N][N][N][N];
int judge(node c)
{
if(mark[c.x][c.y][c.xx][c.yy]==1)
return 0;
if((a[c.x][c.y]&16)==0)
return 0;
if((b[c.xx][c.yy]&16)==0)
return 0;
return 1;
}
int bfs()
{
queue<node>q;
node cur,next;
cur.x=sa.x;
cur.y=sa.y;
cur.xx=sb.x;
cur.yy=sb.y;
if(cur.x==ea.x&&cur.y==ea.y&&cur.xx==eb.x&&cur.yy==eb.y) return 0;
mark[cur.x][cur.y][cur.xx][cur.yy]=1;
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
for(int i=0; i<4; i++)
{
if((a[cur.x][cur.y]&flag[i])==0)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
}
else
{
next.x=cur.x;
next.y=cur.y;
}
if((b[cur.xx][cur.yy]&flag[i])==0)
{
next.xx=cur.xx+dir[i][2];
next.yy=cur.yy+dir[i][3];
}
else
{
next.xx=cur.xx;
next.yy=cur.yy;
}
if(judge(next))
{
vis[next.x][next.y][next.xx][next.yy].x1=cur.x;
vis[next.x][next.y][next.xx][next.yy].y1=cur.y;
vis[next.x][next.y][next.xx][next.yy].x2=cur.xx;
vis[next.x][next.y][next.xx][next.yy].y2=cur.yy;
mark[next.x][next.y][next.xx][next.yy]=1;
// printf("%d %d %d %d %c %d %d %d %d\n",cur.x,cur.y,cur.xx,cur.yy,s[i],next.x,next.y,next.xx,next.yy);
if(next.x==ea.x&&next.y==ea.y&&next.xx==eb.x&&next.yy==eb.y) return 0;
q.push(next);
}
}
}
return 1;
}
void print(int x,int y,int xx,int yy)
{
int tx,ty,txx,tyy;
tx=x;
ty=y;
txx=xx;
tyy=yy;
if(x==sa.x&&y==sa.y&&xx==sb.x&&yy==sb.y) return ;
x=vis[tx][ty][txx][tyy].x1;
y=vis[tx][ty][txx][tyy].y1;
xx=vis[tx][ty][txx][tyy].x2;
yy=vis[tx][ty][txx][tyy].y2;
print(x,y,xx,yy);
for(int i=0; i<4; i++)
{
if((tx+dir[i][0]==x&&ty+dir[i][1]==y)||(txx+dir[i][2]==xx&&tyy+dir[i][3]==yy))
{
if(i==1) i=2;
else if(i==2) i=1;
else if(i==3) i=0;
else if(i==0) i=3;
printf("%c",s[i]);
return ;
}
}
return ;
}
int main()
{
int T;
scanf("%d",&T);
int cnt=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
while(cnt<T)
{
if(cnt%2==0)
{
for(int i=1; i<=6; i++)
{
for(int j=1; j<=6; j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]&32)
{
sa.x=i;
sa.y=j;
}
if(a[i][j]&64)
{
ea.x=i;
ea.y=j;
}
}
}
}
else
{
for(int i=1; i<=6; i++)
{
for(int j=1; j<=6; j++)
{
scanf("%d",&b[i][j]);
if(b[i][j]&32)
{
sb.x=i;
sb.y=j;
}
if(b[i][j]&64)
{
eb.x=i;
eb.y=j;
}
}
}
}
cnt++;
if(cnt<2) continue;
memset(vis,-1,sizeof(vis));
memset(mark,0,sizeof(mark));
if(bfs())
{
printf("-1\n");
continue;
}
print(ea.x,ea.y,eb.x,eb.y);
printf("\n");
}
return 0;
}