//注释不是很多,读懂代码需要耐心。。。。。。读不懂可以在下面留言,我尽量回复。 //希望大家都写赛后总结——写在自己人人或者空间博客内,没写出1002和1004的应该反思一下最近的状态了。。。 /* 1001 开始用dfs递归,爆栈了 后来模拟又因为 出迷宫的条件一直wa,细节很重要 模拟也是一种能力啊,别小看它。。。 */ #include <iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<ctime> using namespace std; #define N 50009 int R,C,ER,EC,num; int map1[505][505]; int map2[505][505]; int vis[505][505]; struct Point { int x,y,f;//f表示当前面向的方向 Point(int _x,int _y,int _f){x=_x;y=_y;f=_f;} }; void init() { scanf("%d%d%d%d",&R,&C,&ER,&EC); memset(vis,0,sizeof(vis)); num=0; for(int i=0;i<2*R-1;i++) { if(i&1) { for(int j=0;j<C;j++) scanf("%d",&map1[i/2][j]); } else { for(int j=0;j<C-1;j++) scanf("%d",&map2[i/2][j]); } } } void dfs(Point s,Point ss) { int ff=s.f; for(;;) { if(!vis[s.x][s.y])num++; vis[s.x][s.y]=1; if(s.x==ss.x&&s.y==ss.y)//注意退出的条件,这里比较复杂 { if((s.f==3&&ff==0)||(s.f==1&&ff==2)) break; if(s.f==ff&&ff==0&&(s.y==0||map2[s.x][s.y-1]==1)) break; if(s.f==ff&&ff==2&&(s.y==C-1||map2[s.x][s.y]==1)) break; } if(s.f==0) { if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } else if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } else if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } else if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } } else if(s.f==1) { if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } else if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } else if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } else if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } } else if(s.f==2) { if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } else if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } else if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } else if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } } else if(s.f==3) { if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } else if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } else if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } else if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } } } } void solve() { Point s=Point(0,ER,0); Point ss=Point(R-1,EC,2); dfs(s,ss); dfs(ss,s); if(num==R*C) puts("YES"); else puts("NO"); } int main() { int Case; scanf("%d",&Case); while(Case--) { init(); solve(); } return 0; } /* 1002 类似用floyed传递闭包,其他的就很easy了 */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n,m; int g[257][257]; void init() { memset(g,0,sizeof(g)); int i; char s[4]; for(i=0;i<n;i++) { scanf("%s",s); if(s[1]!='-') { g[s[1]][s[0]]=1; g[s[0]][s[1]]=-1; } if(s[2]!='-') { g[s[2]][s[0]]=1; g[s[0]][s[2]]=-1; } } } void floyed() { int i,j,k; for(k='A';k<='Z';k++) for(i='A';i<='Z';i++) for(j='A';j<='Z';j++) { if(g[i][k]!=0&&g[k][j]!=0) g[i][j]=g[i][k]+g[k][j]; } } int abs(int x) { return x>0?x:-x; } void solve() { int i; char s[3]; for(i=0;i<m;i++) { scanf("%s",s); if(g[s[0]][s[1]]==0)printf("-\n"); else { for(int k=0;k<abs(g[s[0]][s[1]])-2;k++) printf("great-"); if(g[s[0]][s[1]]==1)printf("parent\n"); else if(g[s[0]][s[1]]==-1)printf("child\n"); else if(g[s[0]][s[1]]>0) printf("grandparent\n"); else printf("grandchild\n"); } } } int main() { while(scanf("%d%d",&n,&m)) { if(n==0&&m==0)break; init(); floyed(); solve(); } return 0; } /* 1003 题意:有一群人,他们要么喜欢狗讨厌猫,要么喜欢猫讨厌狗,在自己喜欢的动物C留下且自己讨厌的动物D他们会happy,求管理员最多让多少人开心 题解:最大独立点集,拆点转换为最大匹配问题,当两个人的喜好有矛盾(既自己喜欢的别人讨厌或讨厌的的被人喜欢)建边,为无向图(既A和B有矛盾必然有B和A有矛盾),所以最大独立集=n-最大匹配/2; */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> using namespace std; int n,m,p; struct person{ bool cat; int like; int hate; }pe[550]; int link[550],map[550][550],vis[550]; void init() { memset(map,0,sizeof(map)); for(int i=0;i<p;i++) for(int j=i+1;j<p;j++) { if(pe[i].cat==!pe[j].cat) //判断i,j是否有矛盾,有矛盾则建双向边 { if(pe[i].like==pe[j].hate||pe[i].hate==pe[j].like) { map[i][j]=map[j][i]=1; } } } } int can(int x) { for(int j=0;j<p;j++) { if(!vis[j]&&map[x][j]) { vis[j]=1; if(link[j]==-1||can(link[j])) { link[j]=x; return 1; } } } return 0; } void solve() //二分匹配 { memset(link,-1,sizeof(link)); int num=0; for(int i=0;i<p;i++) { memset(vis,0,sizeof(vis)); if(can(i)) num++; } printf("%d\n",p-num/2); } int main() { while(scanf("%d%d%d",&n,&m,&p)!=EOF) { char ch1,ch2; int aa,bb; for(int i=0;i<p;i++) { cin>>ch1>>aa>>ch2>>bb; if(ch1=='C') { pe[i].cat=true; pe[i].like=aa; pe[i].hate=bb; } else { pe[i].cat=false; pe[i].like=aa; pe[i].hate=bb; } } init(); solve(); } return 0; } /* 1004 很简单的优先队列模拟题,这个写不出来要好好补补了。。。 */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; int n; struct node { int num; int k; }pp[10009]; struct cmp{ bool operator () (node &a,node &b) { if(a.k<b.k) return true; else if(a.k==b.k&&a.num>b.num) return true; else return false; } }; int main( ) { char s[3]; int a,b; while(scanf("%d",&n)!=EOF) { priority_queue<node,vector<node>,cmp> q[4]; int g=1; while(n--) { scanf("%s",s); if(s[0]=='I') { scanf("%d%d",&a,&b); pp[g].num=g; pp[g].k=b; q[a].push(pp[g]); g++; } if(s[0]=='O') { scanf("%d",&a); if(q[a].empty()) cout<<"EMPTY"<<endl; else{ cout<<q[a].top().num<<endl; q[a].pop(); } } } } return 0; } /* 1005 代码是我写的,解题思路是某大牛博客的,我认为他讲的比我明白。。。 题意:给你一个数,判断其中是否有平方因子。 解题思路:因为题目给我们的数n的范围为:[2,10^18],直接用暴力是无法做的。所以我们先对有平方因子的数进行分析,一个数有平方因子,那么它一定有素数平方因子; 设: n=p1^e1*p2^e2*p3^e3*…pk^ek。(其中p1···pk为素因子),如果e1~ek中有任何一个数为2,则说明X必定有素因子的平方,如果x是两个素因子的乘积,我们就可以直接 这么做:x=sqrt(n),再判断x的平方是不是等于n,来判断n是否有平方因子。如果x当中包括了多个素因子的乘积,那么由三个最大的素因子,这个素因子最大为多大呢 1000000*1000000*10000000=10^18;所以我们只要找出1000000以内的素数,然后在这里找是否有素因子平方。大于这个范围的话,我们就可以认为这个数n最多可能由两个素数成绩组成的,然后用前面那种方法判断是否有平方因子。 */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <set> #include<map> #include<ctime> using namespace std; int isprime[1000001]; __int64 prime[80000]; int num; void getprime() { num=0; for(int i=2;i<=1000000;i++) { if(isprime[i]==0) prime[num++]=i; for(int j=1;j*i<=1000000;j++) { isprime[i*j]=1; } } } __int64 get(__int64 n) { __int64 k=sqrt(n); return k*k; } int main() { int Case; __int64 n; getprime(); scanf("%d",&Case); for(int kk=1;kk<=Case;kk++) { scanf("%I64d",&n); int flag=1; for(int i=0;i<num&&prime[i]*prime[i]<=n;i++)if(n%prime[i]==0) { n=n/prime[i]; if(n%prime[i]==0){flag=0;break;} } if(flag&&n==get(n)){flag=0;} printf("Case %d: ",kk); if(flag)puts("Yes"); else puts("No"); } } /* 1006 好水。。。差点被灌饱 */ #include <iostream> #include <cmath> #include <cstdlib> #include<cstdio> #include<algorithm> #include<cstdio> #include<ctime> #include<cstring> using namespace std; inline int sqr(int x) { return x*x; } int main () { int Case; scanf("%d",&Case); for(int k=1;k<=Case;k++) { int edge[3]; for(int i=0;i<3;i++) scanf("%d",&edge[i]); sort(edge,edge+3); int a,b,c; a=sqr(edge[0]); b=sqr(edge[1]); c=sqr(edge[2]); printf("Case %d: ",k); if(a+b==c) puts("Right triangle"); else { if(a+b-c<0) puts("Obtuse triangle"); else puts("Acute triangle"); } } return 0; } /* 1007 依稀记得给庄大牛卡过这题,我出过trick给他(O_O),怎么暴力自己看吧。很容易懂. */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> #include<map> using namespace std; void rw(); char c[100009]; char s[200009]; int d[200009]; void init(int k){ scanf("%s",c); int len=strlen(c); d[0]=(c[0]=='A')?1:0; strcpy(s,c); strcat(s,c); int a; for(int i=1;i<2*len;i++) { if(s[i]=='A')d[i]=d[i-1]+1; else d[i]=d[i-1]; if(i==len-1)a=d[i]; } int ans=1<<25; for(int i=0;i<len;i++) { int tem=d[i+a]-d[i]; if(a-tem<ans)ans=a-tem; } printf("Case %d: %d\n",k,ans); } void solve(){} int main() { int Case; scanf("%d\n",&Case); for(int i=1;i<=Case;i++) { init(i); } return 0; } /* 1008 有两种情况要特判(因为2是唯一的偶质数嘛。。。)千里之堤毁于蚁穴,完美的程序不容有瑕疵。细节很重要 其实还是暴力程序 如何巧妙的在低复杂度内暴力出结果也是一门艺术,孩纸们。。。。。。 */ #include <iostream> #include <cmath> #include <cstdlib> #include<cstdio> #include<algorithm> #include<cstdio> #include<ctime> #include<cstring> using namespace std; const int N=12000000; bool isprime[N+1]; int prime[8000000]; int num,a,b; void getprime() { num=0; for(int i=2;i<=N;i++) { if(!isprime[i]) { prime[num++]=i; for(int j=2;j*i<=N;j++) isprime[i*j]=1; } } } void solve() { int low=0,hei=num,mid; while(low<hei-1) { mid=(low+hei)>>1; if(prime[mid]==a){hei=mid;break;} else if(prime[mid]>a) { hei=mid; } else low=mid; } for(int i=hei;i<num-1;i++) { int d=prime[i]-a; if(prime[i+1]-b==d) { printf("%d\n",d); return ; } } } int main () { int Case; getprime(); scanf("%d",&Case); for(int i=1;i<=Case;i++) { scanf("%d%d",&a,&b); if(a>b)swap(a,b); printf("Case %d: ",i); if(a==1&&b==2){puts("1");continue;} if(a==2&&b==3) { puts("0"); continue; } if((b-a)&1||a==b)puts("-1"); else { solve(); } } return 0; }