第四周 8.9-8.15
8.9
滚回家。
8.10
终于补了多校6。1006。
补个BC。
HDU 5365 Run
暴力举正方形即可。
(死在正方形判定上。初中没学好。)
1 # include <iostream> 2 # include <cstdio> 3 # include <cmath> 4 using namespace std; 5 6 struct node 7 { 8 int x,y; 9 }p[21]; 10 11 bool judge(int i,int j,int k,int l) 12 { 13 if(p[i].x+p[k].x!=p[j].x+p[l].x) return false; 14 if(p[i].y+p[k].y!=p[j].y+p[l].y) return false; 15 if((p[i].y-p[k].y)*(p[j].y-p[l].y)+(p[i].x-p[k].x)*(p[j].x-p[l].x)) return false; 16 if(2*(pow(p[i].x-p[j].x,2)+pow(p[i].y-p[j].y,2))!=pow(p[i].x-p[k].x,2)+pow(p[i].y-p[k].y,2)) return false; 17 return true; 18 } 19 20 int main(void) 21 { 22 int n; 23 while(~scanf("%d",&n)) 24 { 25 for(int i=1;i<=n;i++) 26 scanf("%d%d",&p[i].x,&p[i].y); 27 int ans=0; 28 for(int i=1;i<=n;i++) 29 { 30 for(int j=1;j<=n;j++) 31 { 32 if(j==i) continue; 33 for(int k=1;k<=n;k++) 34 { 35 if(k==i||k==j) continue; 36 for(int l=1;l<=n;l++) 37 { 38 if(l==i||l==j||l==k) continue; 39 if(judge(i,j,k,l)) ans++; 40 } 41 } 42 } 43 } 44 ans/=8; 45 printf("%d\n",ans); 46 } 47 return 0; 48 }
下午陕多校。心累。不补!
8.11
切菜。
POJ 1331 棋盘问题
八皇后简单版。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 using namespace std; 5 int n,k,map[9][9],col[9],ans; 6 7 void dfs(int r,int rem) 8 { 9 if(rem==0) {ans++; return;} 10 if(r>n) return; 11 for(int i=1;i<=n;i++) 12 { 13 if(!col[i]&&!map[r][i]) 14 { 15 col[i]=1; 16 dfs(r+1,rem-1); 17 col[i]=0; 18 } 19 } 20 if(r<n) dfs(r+1,rem); 21 return; 22 } 23 24 int main(void) 25 { 26 while(~scanf("%d%d",&n,&k)) 27 { 28 if(n==-1) break; 29 for(int i=1;i<=n;i++) 30 { 31 char s[10]; 32 scanf("%s",s+1); 33 for(int j=1;j<=n;j++) 34 map[i][j]=s[j]=='.'?1:0; 35 } 36 ans=0; 37 dfs(1,k); 38 printf("%d\n",ans); 39 } 40 return 0; 41 }
POJ 2251 Dungeon Master
拯救拉面女神。
1 # include <iostream> 2 # include <cstdio> 3 # include <queue> 4 using namespace std; 5 char map[31][31][31]; 6 int L,R,C; 7 int step[][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}}; 8 9 bool in(int l,int r,int c) 10 { 11 return l>0&&l<=L&&r>0&&r<=R&&c>0&&c<=C; 12 } 13 14 struct node 15 { 16 int l,r,c; 17 friend bool operator ==(node a,node b) 18 { 19 return a.l==b.l&&a.r==b.r&&a.c==b.c; 20 } 21 }s,e; 22 typedef pair<node,int> pii; 23 24 int main(void) 25 { 26 while(~scanf("%d%d%d",&L,&R,&C)) 27 { 28 if(!L) break; 29 for(int i=1;i<=L;i++) 30 { 31 for(int j=1;j<=R;j++) 32 { 33 char str[40]; 34 scanf("%s",str+1); 35 for(int k=1;k<=C;k++) 36 { 37 map[i][j][k]=str[k]; 38 if(map[i][j][k]=='S') s={i,j,k}; 39 else if(map[i][j][k]=='E') e={i,j,k}; 40 } 41 } 42 } 43 int ans=-1; 44 queue<pii> q; 45 q.push(pii(s,0)); 46 while(!q.empty()) 47 { 48 pii tem=q.front(); q.pop(); 49 node p=tem.first; 50 int t=tem.second; 51 if(p==e) {ans=t; break;} 52 for(int i=0;i<6;i++) 53 { 54 int x=p.l,y=p.r,z=p.c; 55 x+=step[i][0]; 56 y+=step[i][1]; 57 z+=step[i][2]; 58 if(in(x,y,z)&&map[x][y][z]!='S'&&map[x][y][z]!='#') 59 { 60 node next={x,y,z}; 61 map[x][y][z]='#'; 62 q.push(pii(next,t+1)); 63 } 64 } 65 } 66 if(ans<0) printf("Trapped!\n"); 67 else printf("Escaped in %d minute(s).\n",ans); 68 } 69 return 0; 70 }
POJ 3278 Catch That Cow
水水BFS。
1 # include <iostream> 2 # include <cstdio> 3 # include <cmath> 4 # include <cstring> 5 # include <queue> 6 using namespace std; 7 typedef pair<int,int> pii; 8 queue <pii> q; 9 bool vis[200000]; 10 11 int main(void) 12 { 13 int N,k; 14 while(~scanf("%d%d",&N,&k)) 15 { 16 memset(vis,0,sizeof(vis)); 17 while(!q.empty()) q.pop(); 18 q.push(pii(N,0)); 19 int ans=-1; 20 while(!q.empty()) 21 { 22 pii tem=q.front(); q.pop(); 23 int now=tem.first,t=tem.second; 24 if(now==k) {ans=t;break;} 25 if(fabs(2*now-k)<=fabs(now-k)&&!vis[2*now]) 26 { 27 vis[2*now]=1; 28 q.push(pii(2*now,t+1)); 29 } 30 if(now<k&&!vis[now+1]) 31 { 32 vis[now+1]=1; 33 q.push(pii(now+1,t+1)); 34 } 35 if(now>0&&!vis[now-1]) 36 { 37 vis[now-1]=1; 38 q.push(pii(now-1,t+1)); 39 } 40 } 41 printf("%d\n",ans); 42 } 43 return 0; 44 }
下午多校。老样子。
补题。
8.12
补题。
POJ 3279 Fliptile
噫第一次写二进制枚举。好弱。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <cmath> 5 using namespace std; 6 # define INF 2147483647 7 int grid[16][16],tem[16][16],tem_ans[16][16],ans[16][16]; 8 int mov[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; 9 int M,N,Min; 10 11 void ans_print(void) 12 { 13 for(int i=1;i<=M;i++) 14 { 15 for(int j=1;j<=N;j++) 16 printf("%d ",ans[i][j]); 17 printf("\n"); 18 } 19 return; 20 } 21 22 bool in(int i,int j) 23 { 24 return i>0&&i<=M&&j>0&&j<=N; 25 } 26 27 void judge(int x) 28 { 29 int t=0; 30 memcpy(tem,grid,sizeof(tem)); 31 memset(tem_ans,0,sizeof(tem_ans)); 32 for(int i=1;i<=x;i<<=1) 33 { 34 if(i&x) 35 { 36 t++; 37 int pos=log(i)/log(2)+1; 38 tem_ans[1][pos]=1; 39 if(in(1,pos-1)) tem[1][pos-1]=1-tem[1][pos-1]; 40 if(in(1,pos+1)) tem[1][pos+1]=1-tem[1][pos+1]; 41 tem[1][pos]=1-tem[1][pos]; 42 tem[2][pos]=1-tem[2][pos]; 43 } 44 } 45 for(int i=2;i<M;i++) 46 { 47 for(int j=1;j<=N;j++) 48 { 49 if(tem[i-1][j]) 50 { 51 t++; 52 tem_ans[i][j]=1; 53 tem[i][j]=1-tem[i][j]; 54 for(int k=0;k<4;k++) 55 if(in(i+mov[k][0],j+mov[k][1])) 56 tem[i+mov[k][0]][j+mov[k][1]]=1-tem[i+mov[k][0]][j+mov[k][1]]; 57 } 58 } 59 } 60 for(int j=1;j<=N;j++) 61 { 62 if(in(M,j-1)&&tem[M][j-1]^tem[M-1][j]) return; 63 if(tem[M-1][j]) 64 { 65 t++; 66 tem_ans[M][j]=1; 67 tem[M][j]=1-tem[M][j]; 68 for(int k=0;k<4;k++) 69 if(in(M+mov[k][0],j+mov[k][1])) 70 tem[M+mov[k][0]][j+mov[k][1]]=1-tem[M+mov[k][0]][j+mov[k][1]]; 71 } 72 } 73 if(tem[M][N]) return; 74 if(t<Min) 75 { 76 Min=t; 77 memcpy(ans,tem_ans,sizeof(ans)); 78 } 79 return; 80 } 81 82 int main(void) 83 { 84 scanf("%d%d",&M,&N); 85 for(int i=1;i<=M;i++) 86 for(int j=1;j<=N;j++) 87 scanf("%d",&grid[i][j]); 88 Min=INF; 89 for(int i=0;i<(1<<N);i++) judge(i); 90 if(Min<INF) ans_print(); 91 else puts("IMPOSSIBLE"); 92 return 0; 93 }
POJ 1426 Find The Multiple
因为涉及数学我就不会了。于是最简单的dfs水果。
只要枚举01构成的数。不枚举n的倍数都是可以的。
1 # include <iostream> 2 # include <cstdio> 3 using namespace std; 4 typedef unsigned long long LL; 5 const LL Max=(LL)1000000000000000000; 6 LL ans; 7 int n; 8 9 bool dfs(LL num) 10 { 11 if(num%(LL)n==0) {ans=num;return true;} 12 if(num>Max) return false; 13 if(dfs(num*(LL)10)) return true; 14 if(dfs(num*(LL)10+(LL)1)) return true; 15 return false; 16 } 17 18 int main(void) 19 { 20 while(~scanf("%d",&n)) 21 { 22 if(!n) break; 23 dfs(1); 24 printf("%llu\n",ans); 25 } 26 return 0; 27 }
8.13
POJ 3126 Prime Path
水水BFS。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <queue> 5 using namespace std; 6 typedef pair<int,int> pii; 7 int flag[10000],vis[10000]; 8 queue<pii> q; 9 10 int main(void) 11 { 12 for(int i=2;i<10000;i++) 13 for(int j=2*i;j<10000;j+=i) 14 flag[j]=1; 15 int T; cin>>T; 16 while(T--) 17 { 18 memset(vis,0,sizeof(vis)); 19 int a,b; 20 scanf("%d%d",&a,&b); 21 while(!q.empty()) q.pop(); 22 vis[a]=1; 23 q.push(pii(a,0)); 24 int ans=-1; 25 while(!q.empty()) 26 { 27 pii tem=q.front(); q.pop(); 28 int now=tem.first,t=tem.second; 29 if(now==b) {ans=t;break;} 30 for(int i=0;i<=9;i++) 31 { 32 int next=now/10*10+i; 33 if(!flag[next]&&!vis[next]) 34 q.push(pii(next,t+1)),vis[next]=1; 35 } 36 for(int i=0;i<=9;i++) 37 { 38 int p=now%10; 39 int next=now/100*100+10*i+p; 40 if(!flag[next]&&!vis[next]) 41 q.push(pii(next,t+1)),vis[next]=1; 42 } 43 for(int i=0;i<=9;i++) 44 { 45 int p=now%100; 46 int next=now/1000*1000+100*i+p; 47 if(!flag[next]&&!vis[next]) 48 q.push(pii(next,t+1)),vis[next]=1; 49 } 50 for(int i=1;i<=9;i++) 51 { 52 int next=now%1000+1000*i; 53 if(!flag[next]&&!vis[next]) 54 q.push(pii(next,t+1)),vis[next]=1; 55 } 56 } 57 if(ans>=0) printf("%d\n",ans); 58 else puts("Impossible"); 59 } 60 return 0; 61 }
POJ 3087 Shuffle'm Up
模拟洗牌。有循环就跳出。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 using namespace std; 5 char a[300],b[300],ori[300],next[300],tar[300]; 6 7 int main(void) 8 { 9 int T;cin>>T; 10 for(int kase=1;kase<=T;kase++) 11 { 12 memset(ori,0,sizeof(ori)); 13 memset(next,0,sizeof(next)); 14 int len; scanf("%d",&len); 15 scanf("%s %s %s",a,b,tar); 16 for(int i=0;i<len;i++) 17 { 18 ori[i]=a[i]; 19 ori[i+len]=b[i]; 20 } 21 for(int i=0;i<len;i++) 22 { 23 next[2*i]=b[i]; 24 next[2*i+1]=a[i]; 25 } 26 int t=0,ans=-1; 27 while(strcmp(ori,next)) 28 { 29 t++; 30 if(!strcmp(next,tar)) {ans=t;break;} 31 for(int i=0;i<len;i++) 32 { 33 a[i]=next[i]; 34 b[i]=next[i+len]; 35 } 36 for(int i=0;i<len;i++) 37 { 38 next[2*i]=b[i]; 39 next[2*i+1]=a[i]; 40 } 41 } 42 printf("%d %d\n",kase,ans>0?ans:-1); 43 } 44 return 0; 45 }
多校。low爆。
8.14
补题。看莫队。
8.15
初习莫队小结。
莫队算法用来解决一类无修改的离线区间询问问题。
能使用莫队的问题需要具有这样的特征。
即已知[L,R]的答案。可以推算出[L,R+1],[L-1,R]的答案。
推算这个的时间叫做转移时间。O(1)的最好。O(logN)的也可以尝试一下莫队。
莫队的核心在于对询问预先排序。使得相邻的询问的区间的L,R距离较小。从而通过步数较少的转移找到答案。
如何对询问排序呢?
容易看出。从区间[L1,R1]转移到[L2,R2]的代价是左右端点的曼哈顿距离之和乘上转移时间。
因此最早的方法是把询问看成平面点。再求最小曼哈顿距离树。
由于此方法较为复杂。现在较为常用的是一种方便的替代方法。
先将左端点分成sqrt(N)个块。块内按右端点排序。
分析下复杂度。
考虑右端点。
同一块中的询问处理完右端点最多转移N次。一共sqrt(N)块。所以右端点块内转移最多N*sqrt(N)次。
跨块时。跨一块最多转移N步。跨块最多进行sqrt(N)次。所以右端点跨块转移最多也是N*sqrt(N)次。
考虑左端点。
块内一次最多转移sqrt(N)步。一共M个询问。所以左端点块内转移最多M*sqrt(N)次。
跨一块最多转移2*sqrt(N)步。跨一块最多sqrt(N)次。所以左端点跨块最多转移2N次。
(跨多块的情况:例如一次跨k块。转移的步数为(k+1)*sqrt(N)显然比每次跨一块的2*k*sqrt(N)要少。)
所以当M与N同阶的时候。总的复杂度是N*sqrt(N)*转移时间。
这场多校做的少。花的时间多了。不搞了。
POJ 3414 Pots
BFS。因为要输出路径。所以用数组模拟保存前驱即可。
1 # include <iostream> 2 # include <cstdio> 3 using namespace std; 4 # define maxn 1000000 5 int pre[maxn],vis[101][101]; 6 7 struct node 8 { 9 int l1,l2; 10 int type,i,j; 11 } op[maxn]; 12 13 void ans_print(int pos,int step) 14 { 15 if(pos!=1) ans_print(pre[pos],step+1); 16 else printf("%d\n",step); 17 if(op[pos].type==1) printf("FILL(%d)\n",op[pos].i); 18 else if(op[pos].type==2) printf("DROP(%d)\n",op[pos].i); 19 else if(op[pos].type==3) printf("POUR(%d,%d)\n",op[pos].i,op[pos].j); 20 return; 21 } 22 23 int main(void) 24 { 25 int A,B,C; 26 scanf("%d%d%d",&A,&B,&C); 27 int l=1,r=1,ans=0; 28 node tem,next; 29 tem.l1=tem.l2=0; 30 op[r]=tem; 31 while(l<=r) 32 { 33 tem=op[l]; 34 int l1=tem.l1,l2=tem.l2; 35 if(tem.l1==C||tem.l2==C) {ans=l; break;} 36 if(!vis[A][l2]) 37 { 38 next.type=1; 39 next.i=1; 40 next.l1=A; 41 next.l2=l2; 42 vis[A][l2]=1; 43 op[++r]=next; 44 pre[r]=l; 45 } 46 if(!vis[l1][B]) 47 { 48 next.type=1; 49 next.i=2; 50 next.l1=l1; 51 next.l2=B; 52 vis[l1][B]=1; 53 op[++r]=next; 54 pre[r]=l; 55 } 56 if(!vis[0][l2]) 57 { 58 next.type=2; 59 next.i=1; 60 next.l1=0; 61 next.l2=l2; 62 vis[0][l2]=1; 63 op[++r]=next; 64 pre[r]=l; 65 } 66 if(!vis[l1][0]) 67 { 68 next.type=2; 69 next.i=2; 70 next.l1=l1; 71 next.l2=0; 72 vis[l1][0]=1; 73 op[++r]=next; 74 pre[r]=l; 75 } 76 if(l1+l2<=A&&!vis[l1+l2][0]) 77 { 78 next.type=3; 79 next.i=2; 80 next.j=1; 81 next.l1=l1+l2; 82 next.l2=0; 83 vis[l1+l2][0]=1; 84 op[++r]=next; 85 pre[r]=l; 86 } 87 if(l1+l2>A&&!vis[A][l1+l2-A]) 88 { 89 next.type=3; 90 next.i=2; 91 next.j=1; 92 next.l1=A; 93 next.l2=l1+l2-A; 94 vis[A][l1+l2-A]=1; 95 op[++r]=next; 96 pre[r]=l; 97 } 98 if(l1+l2<=B&&!vis[0][l1+l2]) 99 { 100 next.type=3; 101 next.i=1; 102 next.j=2; 103 next.l1=0; 104 next.l2=l1+l2; 105 vis[0][l1+l2]=1; 106 op[++r]=next; 107 pre[r]=l; 108 } 109 if(l1+l2>B&&!vis[l1+l2-B][B]) 110 { 111 next.type=3; 112 next.i=1; 113 next.j=2; 114 next.l1=l1+l2-B; 115 next.l2=B; 116 vis[l1+l2-B][B]=1; 117 op[++r]=next; 118 pre[r]=l; 119 } 120 l++; 121 } 122 if(ans) ans_print(ans,0); 123 else puts("impossible"); 124 return 0; 125 }
FZU 2150 Fire Game
水水BFS。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <queue> 6 using namespace std; 7 typedef pair<int,int> pii; 8 typedef pair<pii,int> piii; 9 int n,m; 10 int map[11][11],cpy[11][11]; 11 int step[][2]={{0,1},{0,-1},{1,0},{-1,0}}; 12 queue<piii> q; 13 14 bool in(int i,int j) 15 { 16 return i>0&&i<=n&&j>0&&j<=m; 17 } 18 19 int main(void) 20 { 21 int T; cin>>T; 22 for(int kase=1;kase<=T;kase++) 23 { 24 scanf("%d%d",&n,&m); 25 int tot=0,ans=-1; 26 for(int i=1;i<=n;i++) 27 { 28 char s[20]; 29 scanf("%s",s+1); 30 for(int j=1;j<=m;j++) 31 { 32 map[i][j]=(s[j]=='#')?1:0; 33 tot+=map[i][j]; 34 } 35 } 36 for(int i=1;i<=n;i++) 37 for(int j=1;j<=m;j++) 38 for(int k=i;k<=n;k++) 39 for(int l=(k==i)?j:1;l<=m;l++) 40 { 41 if(!map[i][j]||!map[k][l]) continue; 42 int cnt=0,t; 43 memcpy(cpy,map,sizeof(map)); 44 while(!q.empty()) q.pop(); 45 q.push(piii(pii(i,j),0)); 46 cpy[i][j]=0; cnt++; 47 if(i!=k||j!=l) 48 { 49 q.push(piii(pii(k,l),0)); 50 cpy[k][l]=0; 51 cnt++; 52 } 53 while(!q.empty()) 54 { 55 piii tem=q.front();q.pop(); 56 int x=tem.first.first,y=tem.first.second; 57 t=tem.second; 58 for(int p=0;p<4;p++) 59 { 60 int xx=x+step[p][0],yy=y+step[p][1]; 61 if(!in(xx,yy)||!cpy[xx][yy]) continue; 62 cpy[xx][yy]=0; cnt++; 63 q.push(piii(pii(xx,yy),t+1)); 64 } 65 } 66 if(cnt==tot) ans=ans<0?t:min(ans,t); 67 } 68 printf("Case %d: %d\n",kase,ans); 69 } 70 return 0; 71 }
晚上BC爆O。待补。