T1,不多说,pascal自带的pos轻松过,枚举第一个删AC或CA,水过~~
T2,meet in the middle,不过在用扩欧的时候要注意如果ex_gcd(a,b,x,y)中的a或b=0,直接退出。炸了85分~~
T3,一个暴力,靠着没有正确性的暴力居然有50分,感人。
总结:T2这种数学题对边界如0这种还是要好好思考一下的,比如说如果用费马小定理求逆元的话更加要注意了p=2的情况(YHYHYH3提醒)
写一下T3的题。
这道题我写了一个广搜,其实正解也是广搜,一般我们广搜都是对(x,y)的二元组惊醒搜索的,但是这道题我们发现一条蛇可以多次走一个点(不多于两次吧),所以我们要加入另一个状态(x,y,body),表示其蛇头在这个点时的姿态?因为len<=8(哦照片没拍出来),所以我们可以用压位来操作。
#include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #include <algorithm> using namespace std; typedef long long ll; int n, m, l, x, y, x2, y2; int cx[4] = {1, 0, -1, 0}; int cy[4] = {0, 1, 0, -1}; int head, tail, i, j, k, num, dk, ans; bool flag; struct Node { int x, y, z; } d[8000000]; int b[29][29][24010], f[29][29][24010], snackx[10], snacky[10], F[2100][2100], T[10]; bool abletogo[2100][2100]; int main() { freopen("snake.in", "r", stdin); freopen("snake.out", "w", stdout); int t; scanf("%d", &t); while (t--) { scanf("%d%d%d", &n, &m, &l); if (l == 1) { for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) abletogo[i][j] = 0, F[i][j] = -1; scanf("%d%d", &x, &y); abletogo[x][y] = 1; head = tail = 1; d[tail].x = x; d[tail].y = y; F[x][y] = 0; scanf("%d", &k); for (int i = 1; i <= k; i++) { scanf("%d%d", &x, &y); abletogo[x][y] = 1; } while (head <= tail) { for (int i = 0; i < 4; i++) { x2 = d[head].x + cx[i]; y2 = d[head].y + cy[i]; if (x2 < 1 || x2 > n || y2 < 1 || y2 > m || abletogo[x2][y2]) continue; abletogo[x2][y2] = 1; F[x2][y2] = F[d[head].x][d[head].y] + 1; tail++; d[tail].x = x2; d[tail].y = y2; } head++; } printf("%d ", F[1][1]); } else { for (int i = 1; i <= l; i++) scanf("%d%d", &snackx[i], &snacky[i]); num = 0; for (int i = 1; i < l; i++) { for (int j = 0; j < 4; j++) if (snackx[i] + cx[j] == snackx[i + 1] && snacky[i] + cy[j] == snacky[i + 1]) { num = num * 4 + j; break; } } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) for (int dk = 0; dk <= 1 << 14; dk++) b[i][j][dk] = 0, f[i][j][dk] = -1; b[snackx[1]][snacky[1]][num] = 1; f[snackx[1]][snacky[1]][num] = 0; head = tail = 1; d[tail].x = snackx[1]; d[tail].y = snacky[1]; d[tail].z = num; scanf("%d", &k); for (int i = 1; i <= k; i++) { scanf("%d%d", &x, &y); for (int j = 0; j <= 1 << 14; j++) b[x][y][j] = 1; } while (head <= tail) { num = d[head].z; for (int i = l - 1; i; i--) { T[i] = num % 4; num /= 4; } snackx[1] = d[head].x, snacky[1] = d[head].y; for (int i = 1; i <= l - 1; i++) { snackx[i + 1] = snackx[i] + cx[T[i]]; snacky[i + 1] = snacky[i] + cy[T[i]]; } for (int i = 0; i < 4; i++) { x2 = snackx[1] + cx[i]; y2 = snacky[1] + cy[i]; if (x2 < 1 || x2 > n || y2 < 1 || y2 > m) continue; flag = false; for (int j = 1; j <= l - 1; j++) if (x2 == snackx[j] && y2 == snacky[j]) { flag = true; break; } if (flag) continue; num = (i + 2) % 4; for (int j = 1; j < l - 1; j++) num = num * 4 + T[j]; if (b[x2][y2][num]) continue; b[x2][y2][num] = 1; f[x2][y2][num] = f[d[head].x][d[head].y][d[head].z] + 1; tail++; d[tail].x = x2; d[tail].y = y2; d[tail].z = num; } head++; } ans = INT_MAX; for (int i = 0; i <= 1 << 14; i++) if (f[1][1][i] != -1) ans = min(ans, f[1][1][i]); if (ans == INT_MAX) printf("-1 "); else printf("%d ", ans); } } }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define ll long long int n,m,z,L,body,step=-1; int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0},Pow[10]; int change[20000][4]; bool f[20000],flag[21][21][20000],duang[2011][2011],bo[100][100]; struct snake{ int x[8],y[8],z,body; }s,news; queue<snake> Q; int calc_body(snake s) { int id=0; for(int i=1;i<L;i++) { int cx=s.x[i]-s.x[i-1],cy=s.y[i]-s.y[i-1]; int j=0; for(j=0;j<4;j++) { if(dx[j]==cx&&dy[j]==cy) break; } id=id*4+j; } return id; } void solve() { while(!Q.empty()) Q.pop(); s.body=calc_body(s); Q.push(s); flag[s.x[0]][s.y[0]][s.body]=1; while(!Q.empty()&&step==-1) { s=Q.front();Q.pop(); for(int i=0;i<4;i++) { int x=s.x[0]+dx[i],y=s.y[0]+dy[i],z=s.z+1,body=change[s.body][i]; if(x<=0||x>n||y<=0||y>m||flag[x][y][body]||duang[x][y]||(!f[body])) continue; if(x==1&&y==1) { step=z; break; } news.z=z;news.x[0]=x,news.y[0]=y;news.body=body; Q.push(news); flag[x][y][body]=1; } } cout<<step<<endl; } void bfs() { while(!Q.empty()) Q.pop(); Q.push(s); duang[s.x[0]][s.y[0]]=1; while(!Q.empty()) { s=Q.front(); Q.pop(); for(int i=0;i<4;i++) { int x=s.x[0]+dx[i],y=s.y[0]+dy[i],z=s.z+1; if(x<=0||x>n||y<=0||y>m||duang[x][y])continue; if(x==1&&y==1) { step=z;break;} news.x[0]=x,news.y[0]=y,news.z=z; Q.push(news); duang[x][y]=1; } } cout<<step<<endl; } void prepare() { Pow[0]=1; for(int i=1;i<10;i++) Pow[i]=Pow[i-1]*4; for(int i=0;i<Pow[L-1];i++)//除了头以外每一位都由原先的高一位来代替,最高位就是当前的方向啦 for(int j=0;j<4;j++) { change[i][j]=i/4+(j+2)%4*Pow[L-2]; } //判断一个蛇是否会碰到自己 memset(f,true,sizeof(f)); for(int i=0;i<Pow[L-1];i++) { memset(bo,0,sizeof(bo)); int x=10,y=10;//随便从中间找一个点向4周扩展 bo[x][y]=1; for(int j=L-1;j>=1;j--) { int t=i%Pow[j]/Pow[j-1]; x+=dx[t];y+=dy[t]; if(bo[x][y]) { f[i]=false; break; } bo[x][y]=1; } } } int main() { int T; scanf("%d",&T); while(T--) { step=-1; memset(flag,0,sizeof(flag)); memset(duang,0,sizeof(duang)); scanf("%d %d %d",&n,&m,&L); prepare(); for(int i=0;i<L;i++) scanf("%d %d",&s.x[i],&s.y[i]); s.z=0; int k; scanf("%d",&k); for(int i=1;i<=k;i++) { int a,b; scanf("%d %d",&a,&b); duang[a][b]=true; } if(s.x[0]==1&&s.y[0]==1) { cout<<0<<endl; continue; } if(L==1) bfs(); else solve(); } return 0; }