集训队例赛——20110925 解题报告

来源:互联网 发布:linux中查看日志文件 编辑:程序博客网 时间:2024/06/05 14:54
//注释不是很多,读懂代码需要耐心。。。。。。读不懂可以在下面留言,我尽量回复。//希望大家都写赛后总结——写在自己人人或者空间博客内,没写出1002和1004的应该反思一下最近的状态了。。。/*1001开始用dfs递归,爆栈了后来模拟又因为 出迷宫的条件一直wa,细节很重要模拟也是一种能力啊,别小看它。。。*/#include <iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<ctime>using namespace std;#define N 50009int 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;}