A - A计划
题意:中文题很好理解;
思路:开个三维数组来存放地图,bfs板子,只是在"#"的地方要换下位置就可以了。
AC代码:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<algorithm> #include<queue> #include<map> #include<iostream> using namespace std; #define inf 0x3f3f3f3f #define ll long long #define mod 1000000007 #define eps 1e-9 #define PI acos(-1.0) #define mem(a,b) memset(a,b,sizeof(a)) char s[3][12][12];//三维数组存图 int n,m,k,a[10],t; int book[12][12][12];//三维数组标记 int to[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};//四个方向 struct node { int w,x,y,step; }; void bfs() { queue<node>q; node u,v; u.x=0,u.y=0; u.w=0,u.step=0; book[0][0][0]=1; q.push(u); while(!q.empty()) { u=q.front(); q.pop(); if(s[u.w][u.x][u.y]=='P'&&u.step<=k)//满足条件输出结果 printf("YES\n"); return; } for(int i=0; i<4; i++) { int dx=u.x+to[i][0]; int dy=u.y+to[i][1]; if(dx>=0&&dx<n&&dy>=0&&dy<m&&s[u.w][dx][dy]!='*')//判断条件 { v.x=dx,v.y=dy,v.step=u.step+1,v.w=u.w; if(s[u.w][dx][dy]=='#') { if(s[1-u.w][dx][dy]=='#'||s[1-u.w][dx][dy]=='*') continue; else v.w=1-u.w; } if(!book[v.w][dx][dy]) { book[v.w][dx][dy]=1; q.push(v); } } } } printf("NO\n"); return ; } int main() { scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); mem(book,0); for(int i=0; i<n; i++) scanf("%s",s[0][i]); for(int i=0; i<n; i++) scanf("%s",s[1][i]); bfs(); } }
B - 非常可乐
题意:中文题。
思路:当状态中的t,n,m任意两个为t/2时,说明存在最小要倒次数,直接模拟倒水的过程,一共六种情况,把每一种情况都考虑一遍,代码如下。
AC代码:
#include<stdio.h> #include<string.h> #include<queue> 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<node>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; }
C - 哈密顿绕行世界问题
题意:这个一道简单的深搜题,并输出路径,把所有的情况都输出出来。
思路:直接用深搜板子写即可,注意细节我在代码中注释出来,不要被它的输出吓到了。
AC代码:
#include<stdio.h> #include<string.h> #include<algorithm> 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; }
D - The Center of Gravity
题意:三角形的三个点的坐标,求出这个三角形的重心。
思路:超级简单的一道题,套用公式即可:。
AC代码:
#include<stdio.h> #include<string.h> #include<algorithm> 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); } } }
E - Eight
题意:给一个状态让你变成给定状态12345678X,输出路径,如果不行输出unsolvable;注意:路径不唯一。
思路:把所有的情况都列出来,例1 2 3 4 5 6 7 x 8,只需将x向右移动一次,并记录这个路径。康托展开:详细介绍:https://blog.youkuaiyun.com/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<iostream> #include<stdio.h> #include<string.h> #include<queue> 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<node>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<d; i++) if(n[i]!=' ') m[f++]=n[i]; if(m[0]=='E'&&m[1]=='O'&&m[2]=='F') break; int ff=0; for(int i=0; i<f; i++) { if(m[i]!='x') w[ff++]=m[i]-48; if(m[i]=='x') w[ff++]=9; } int num=0; 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]; } 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
F - Magic Cube
题意:给出魔方六面,每一面标号如上,给出一种排列,你需要把它复原,求最少步数和步骤,不能超过5步。1表示顺时针,-1表示逆时针。
思路:用IDA*搜索,因为中心颜色确定,找出每个面与中心颜色不同的数量, 每次旋转最多改变12个, 当不同数量/12>深度时剪枝。
AC代码:
#include<stdio.h> #include<string.h> #include<queue> #include<math.h> #include<stdlib.h> #include<map> #include<iostream> #include<vector> #include<stack> #include<algorithm> using namespace std; #define inf 0x3f3f3f3f #define ll long long #define mod 1000000007 #define mem(a,b) memset(a,b,sizeof(a)) #define PI acos(-1.0) #define eps 1e-8 #define N 1000100 int n,m; int flag,sum,res[10]; int row[6][8]= { {0,1,2,3,5,6,7,8},{9,10,11,21,23,33,34,35},{12,13,14,24,26,36,37,38}, {15,16,17,27,29,39,40,41},{18,19,20,30,32,42,43,44},{45,46,47,48,50,51,52,53} }; int change[12][20]= { {11,23,35,34,33,21,9,10,51,48,45,36,24,12,6,3,0,20,32,44}, {9,10,11,23,35,34,33,21,36,24,12,6,3,0,20,32,44,51,48,45}, {14,13,26,38,37,36,24,12,45,46,47,39,27,15,8,7,6,11,23,35}, {12,24,13,14,26,38,37,36,39,27,15,8,7,6,11,23,35,45,46,47}, {17,29,41,40,39,27,15,16,47,50,53,42,30,18,2,5,8,14,26,38}, {15,16,17,29,41,40,39,27,42,30,18,2,5,8,14,26,38,47,50,53}, {18,19,20,32,44,43,42,30,53,52,51,33,21,9,0,1,2,17,29,41}, {42,30,18,19,20,32,44,43,33,21,9,0,1,2,17,29,41,53,52,51}, {0,1,2,5,8,7,6,3,12,13,14,15,16,17,18,19,20,9,10,11}, {6,3,0,1,2,5,8,7,15,16,17,18,19,20,9,10,11,12,13,14}, {45,46,47,50,53,52,51,48,44,43,42,41,40,39,38,37,36,35,34,33}, {51,48,45,46,47,50,53,52,41,40,39,38,37,36,35,34,33,44,43,42} }; int cen[6]= {4,22,25,28,31,49}; char s[11],c[60],ct[60]; int lenn(char *tmp) { int ans=0; for(int i=0; i<6; i++) { int t=0; for(int j=0; j<8; j++) if(tmp[row[i][j]]!=tmp[cen[i]]) t++; ans=max(ans,t); } return (ans+2)/3; } void IDAstar(int step, char a[], int fa) { int t=lenn(a); if(step+t>sum) return; if(!t) { flag=1; return; } char tmp[60]; for(int i=0; i<12; i++) { if((fa^i)==1) continue; memcpy(tmp,a,60*sizeof(char)); res[step]=i; for(int j=0; j<20; j++) tmp[change[i][j]] = a[change[i^1][j]]; IDAstar(step+1,tmp,i); if(flag) return; } } int main() { int i,j,k,kk,t,x,y,z; scanf("%d",&k); while(k--) { for(i=0; i<54; i++) { scanf("%s",s); c[i]=s[0]; } flag=0; sum=lenn(c); while(sum<=5) { IDAstar(0,c,-1); if(flag) { printf("%d\n",sum); for(i=0; i<sum; i++) printf("%d %d ",res[i]/2,(res[i]&1)?-1:1); if(sum) printf("\n"); break; } sum++; } if(!flag) printf("-1\n"); } return 0; }