题意:中文题很好理解;
思路:开个三维数组来存放地图,bfs板子,只是在"#"的地方要换下位置就可以了。
AC代码:
#include
#include #include #include #include #include #include
题意:中文题。
思路:当状态中的t,n,m任意两个为t/2时,说明存在最小要倒次数,直接模拟倒水的过程,一共六种情况,把每一种情况都考虑一遍,代码如下。
AC代码:
#include
#include #include using namespace std; struct node { int x,y,step,z; }; int t,n,m; int book[120][120][119];//标记三个瓶子的状态 void dfs() { node v,u; queue q; u.x=0; u.y=0; u.step=0; u.z=t; book[t][0][0]=1; q.push(u); while(!q.empty()) { u=q.front(); q.pop(); v=u; if(u.z==t/2&&(u.x==t/2||u.y==t/2))//满足条件输出 { printf("%d\n",u.step); return; } for(int i=0; i<6; i++)//一共六种情况,自己推导一下 { if(i==0)//z-->x(表示z瓶的可乐倒入x瓶,同下) { if(u.z+u.x>=n) { v.x=n; v.z=u.z+u.x-n; } else { v.x=u.z+u.x; v.z=0; } v.y=u.y; } if(i==1)//z-->y { if(u.z+u.y>=m) { v.z=u.z+u.y-m; v.y=m; } else { v.z=0; v.y=u.y+u.z; } v.x=u.x; } if(i==2)//x-->y { if(u.x+u.y>=m) { v.x=u.x+u.y-m; v.y=m; } else { v.x=0; v.y=u.x+u.y; } v.z=u.z; } if(i==3)//y-->x { if(u.x+u.y>=n) { v.x=n; v.y=u.x+u.y-n; } else { v.x=u.x+u.y; v.y=0; } v.z=u.z; } if(i==4)//x-->z { v.z=u.z+u.x; v.x=0; v.y=u.y; } if(i==5)//y-->z { v.z=u.z+u.y; v.y=0; v.x=u.x; } if(book[v.z][v.x][v.y]==0) { book[v.z][v.x][v.y]=1; v.step=u.step+1; q.push(v); } } } printf("NO\n"); } int main() { while(~scanf("%d%d%d",&t,&n,&m)&&(t||n||m)) { memset(book,0,sizeof(book)); if(t%2==1)//进行特判,如果t不能被二整除直接输出NO { printf("NO\n"); continue; } else dfs(); } return 0; }
题意:这个一道简单的深搜题,并输出路径,把所有的情况都输出出来。
思路:直接用深搜板子写即可,注意细节我在代码中注释出来,不要被它的输出吓到了。
AC代码:
#include
#include #include using namespace std; int s[21][3],d[21]; int n,book[30],l; void dfs(int x,int y) { if(y==20&&(s[x][0]==d[0]||s[x][1]==d[0]||s[x][2]==d[0]))//满足条件输出一种结果 { printf("%d: ",l++);//注意输出格式 for(int i=0; i<20; i++) { printf("%d ",d[i]); } printf("%d",d[0]); printf("\n"); return ; } for(int j=0; j<=2; j++) { if(book[s[x][j]]==0) { book[s[x][j]]=1; d[y]=s[x][j];//记录路径 int t=s[x][j]; dfs(t,y+1); book[s[x][j]]=0;//注意返回之后要取消标记 } } return ; } int main() { for(int i=1; i<=20; i++) { for(int j=0; j<=2; j++) scanf("%d",&s[i][j]); sort(s[i],s[i]+3); } while(~scanf("%d",&n)&&n!=0) { memset(book,0,sizeof(book));//注意标记数组清空 book[n]=1; d[0]=n; l=1; dfs(n,1); } return 0; }
题意:三角形的三个点的坐标,求出这个三角形的重心。
AC代码:
#include
#include #include using namespace std; int main() { int n; double x1,x2,x3,y1,y2,y3; while(~scanf("%d",&n)&&n) { while(n--) { scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3); double x=(x1+x2+x3)/3.0; double y=(y1+y2+y3)/3.0; printf("%.1f %.1f\n",x,y); } } }
题意:给一个状态让你变成给定状态12345678X,输出路径,如果不行输出unsolvable;注意:路径不唯一。
思路:把所有的情况都列出来,例1 2 3 4 5 6 7 x 8,只需将x向右移动一次,并记录这个路径。康托展开:详细介绍:https://blog.csdn.net/qq_38701476/article/details/81003290 大家也可以用map容器进行存路径,也是可以的。
康托展开的代码:
for(int i=0; i<9; i++) { int ll=0; for(int j=i+1; j<9; j++) if(w[i]>w[j]) ll=ll+1; num=num+ll*jc[8-i]; }
AC代码:
#include
#include #include #include using namespace std; struct node { int h,x,y,z,b[5][5];//x横坐标,y纵坐标 }; int s[5][5],book[400000],jc[11]; char book1[400000]; int to[4][2]= {{1,0},{0,1},{-1,0},{0,-1}} ;//方向d,r,u,l; void bfs() { queue q; node u,v; u.h=9; u.x=2; u.y=2; u.z=0; for(int i=0; i<3; i++) for(int j=0; j<3; j++) u.b[i][j]=s[i][j]; book[0]=0; q.push(u); while(!q.empty()) { u=q.front(); q.pop(); for(int i=0; i<4; i++) { v=u; int dx=u.x+to[i][0]; int dy=u.y+to[i][1]; if(dx>=0&&dx<3&&dy>=0&&dy<3) { v.h=u.b[dx][dy]; v.x=dx; v.y=dy; int tt;//交换位置 tt=u.b[dx][dy]; v.b[dx][dy]=u.b[u.x][u.y]; v.b[u.x][u.y]=tt; int kk[10]; int o=0; for(int i=0; i<3; i++) for(int j=0; j<3; j++) kk[o++]=v.b[i][j]; int sum=0; for(int i=0; i<9; i++)//康托展开 { int l=0; for(int j=i+1; j<9; j++) if(kk[i]>kk[j]) l=l+1; sum=sum+l*jc[8-i]; } v.z=sum; if(book[sum]==-1)//记录路径 { book[sum]=u.z; if(i==0) book1[sum]='u'; if(i==1) book1[sum]='l'; if(i==2) book1[sum]='d'; if(i==3) book1[sum]='r'; q.push(v); } } } } } int main() { int t=1; for(int i=0; i<3; i++) for(int j=0; j<3; j++) s[i][j]=t++; for(int i=0; i<400000; i++) book[i]=-1; jc[0]=0; jc[1]=1; for(int i=2; i<9; i++)//阶乘 jc[i]=i*jc[i-1]; bfs(); char n[100],m[10]; int w[10]; while(gets(n)) { int d=strlen(n),f=0; for(int i=0; i w[j]) ll=ll+1; num=num+ll*jc[8-i]; } if(book[num]==-1) printf("unsolvable"); else while(num!=0) { printf("%c",book1[num]); num=book[num]; } printf("\n"); } return 0; } //1 2 3 4 x 5 6 7 8 rdllurdrulldrr
题意:给出魔方六面,每一面标号如上,给出一种排列,你需要把它复原,求最少步数和步骤,不能超过5步。1表示顺时针,-1表示逆时针。
思路:用IDA*搜索,因为中心颜色确定,找出每个面与中心颜色不同的数量, 每次旋转最多改变12个, 当不同数量/12>深度时剪枝。
AC代码:
#include
#include #include #include #include #include