A ARK
搜素加剪枝。
写完了题发现T了,折腾半天,发现题意理解错了。题意中的每班公交的起始时间i必须小于间隔时间j(因为是班车,在时间i之前公交还有停靠过,只是这些停靠不在12:00至12:59的范围内)。而我理解成了起始时间i之前公交没有停靠过(企业级李姐),导致多算了公交班次的类型,导致了TLE。。。
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 2000 using namespace std; int ans,n,tot,cnt[65]; struct node { int a,b,times; }e[2000]; bool cmp(node x,node y){return x.times>y.times;} int jud(int x,int y) { int re=0; while (x<60) { if (!cnt[x]) return 0; x+=y;re++; } return re; } void dfs(int k,int x,int num) { if (x>=ans) return; if (num==n) { if (x<ans) ans=x; return; } int i,j; for (i=k;i<=tot;i++) { if (x+(n-num)/e[i].times>=ans) return; if (!jud(e[i].a,e[i].b)) continue; for (j=0;j<e[i].times;j++) cnt[e[i].a+e[i].b*j]--; dfs(i,x+1,num+e[i].times); for (j=0;j<e[i].times;j++) cnt[e[i].a+e[i].b*j]++; } } int main() { int i,j,k,x,re; while (scanf("%d",&n)!=EOF) { memset(cnt,0,sizeof(cnt)); tot=0; for (i=1;i<=n;i++) { scanf("%d",&x); cnt[x]++; } for (i=0;i<30;i++) for (j=i+1;i+j<60;j++) { re=jud(i,j); if (re>=2) { e[++tot].a=i; e[tot].b=j; e[tot].times=re; } } sort(e+1,e+tot+1,cmp); ans=17; dfs(1,0,0); printf("%d ",ans); } return 0; }
跑一遍马拉车,枚举第一部分回文串中心i,再枚举第三部分的回文串中心j。如果以这两点为中心的最长回文串都可以覆盖两部分之间的第二部分,即j-i<=min(p[i],p[j]),则符合题意。其中j-i为第二部分的长度的两倍(因为马拉车插入了新数,所以是两倍),所以答案就是(j-i)/2*3。统计其中的最大值即可。
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 200005 #define inf 1000000005; using namespace std; int p[maxn],len,a[maxn],s[maxn]; void manacher() { int mx=0,id,i; for (i=1;i<len;i++) { if (mx>i) p[i]=min(p[2*id-i],mx-i); else p[i]=1; while (s[i+p[i]]==s[i-p[i]]) p[i]++; if (i+p[i]>mx) { id=i; mx=i+p[i]; } } } int main() { int t,i,j,k,x,y,ans; scanf("%d",&t); for (k=1;k<=t;k++) { scanf("%d",&len); for (i=0;i<len;i++) scanf("%d",&a[i]); memset(p,0,sizeof(p)); for (i=0;i<len;i++) { s[i*2+1]=a[i]; s[i*2+2]=inf; } len=len*2; s[0]=inf-1; s[++len]=inf-2; manacher(); ans=0; for (i=0;i<len;i+=2)//对称,回文串中心为'#',所以+=2 for (j=i+p[i]-1;j>i;j-=2) { if (j-i<=ans) break; if (j-p[j]<=i) ans=j-i; } printf("Case #%d: %d ",k,ans/2*3); } return 0; }
F Fallout
给一个地图,地图中1表示障碍物,现在给定机器人的初始位置与初始朝向,机器人每次操作可以向面向的方向走1或2或3个单位,也可以向右或者向左转90度,求机器人到达目标位置所需的最小操作数。
求最短路,明显的bfs。(所以为什么我没写出来。。)需要注意机器人占地4个单位格子,需要判断这四个格子都没有障碍物才能走。
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 52 using namespace std; int n,m,sx,sy,tx,ty; int mp[maxn][maxn],vis[maxn][maxn][4],dis[maxn][maxn][4]; int dr[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//北0东1南2西3 struct node { int x,y,d; }q[10010]; int bfs(int x,int y,int dir) { int l=0,r=0,dd,xx,yy,i; q[++r].x=x; q[r].y=y; q[r].d=dir; vis[x][y][dir]=1; dis[x][y][dir]=0; while (l<r) { x=q[++l].x; y=q[l].y; dir=q[l].d; if (tx==x && ty==y) return dis[x][y][dir]; for (i=1;i<=3;i++) { xx=x+i*dr[dir][0]; yy=y+i*dr[dir][1]; if (xx<1 || xx>=n || yy<1 || yy>=m) break; if (mp[xx][yy] || mp[xx+1][yy] || mp[xx][yy+1] || mp[xx+1][yy+1]) break; if (!vis[xx][yy][dir]) { vis[xx][yy][dir]=1; q[++r].x=xx; q[r].y=yy; q[r].d=dir; dis[xx][yy][dir]=dis[x][y][dir]+1; } } dd=(dir-1+4)%4;//左转 if (!vis[x][y][dd]) { vis[x][y][dd]=1; q[++r].x=x; q[r].y=y; q[r].d=dd; dis[x][y][dd]=dis[x][y][dir]+1; } dd=(dir+1)%4;//右转 if (!vis[x][y][dd]) { vis[x][y][dd]=1; q[++r].x=x; q[r].y=y; q[r].d=dd; dis[x][y][dd]=dis[x][y][dir]+1; } } return -1; } int main() { int i,j,d; char s[10]; while (scanf("%d%d",&n,&m)!=EOF && (n!=0 || m!=0)) { memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); for (i=1;i<=n;i++) for (j=1;j<=m;j++) scanf("%d",&mp[i][j]); scanf("%d%d%d%d%s",&sx,&sy,&tx,&ty,s); if (s[0]=='n') d=0; else if (s[0]=='e') d=1; else if (s[0]=='s') d=2; else d=3; printf("%d ",bfs(sx,sy,d)); } return 0; }
H Halo
异或知识+tries树
计算从根节点到每个点的异或距离,再从中找出两个异或后值最大的即可。
#include<cstring> #include<cstdio> #include<algorithm> #define maxn 100100 using namespace std; typedef long long ll; struct node { int to,nxt,w; }e[maxn*2]; int num,last[maxn],ch[maxn*32][2],cnt; ll f[maxn],note[maxn*32]; void add(int x,int y,int z) { e[++num].to=y; e[num].nxt=last[x]; last[x]=num; e[num].w=z; } void build(ll now) { int i,u=0,x; for (i=31;i>=0;i--) { x=(now>>i)&1; if (!ch[u][x]) ch[u][x]=++cnt; u=ch[u][x]; } note[u]=now; } ll find(ll now) { int i,u=0,x; for (i=31;i>=0;i--) { x=(now>>i)&1; if (ch[u][x^1]) u=ch[u][x^1]; else u=ch[u][x]; } return note[u]; } void dfs(int fa,int x) { for (int i=last[x];i!=-1;i=e[i].nxt) { if (e[i].to==fa) continue; f[e[i].to]=f[x]^e[i].w; dfs(x,e[i].to); } } int main() { int n,x,y,z,i; ll tmp,ans; while (scanf("%d",&n)!=EOF) { memset(last,-1,sizeof(last)); memset(f,0,sizeof(f)); memset(ch,0,sizeof(ch)); memset(note,0,sizeof(note)); num=0;cnt=0;ans=0; for (i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } build(0); dfs(0,0); for (i=0;i<n;i++) build(f[i]); for (i=0;i<n;i++) { tmp=find(f[i])^f[i]; if (tmp>ans) ans=tmp; } printf("%lld ",ans); } return 0; }
I Icey