20130310

来源:互联网 发布:巴黎 知乎 编辑:程序博客网 时间:2024/06/06 04:26


周赛被虐的太惨了,加油吧!!!

http://acm.hdu.edu.cn/diy/contest_show.php?cid=18641

第一题:

题意:三维搜索,从(0,0,0)到(a-1,b-1,c-1).

思路:DFS+回溯写了很长时间,结果总超时,其实是用BFS加剪枝就可以过了。BFS写的过程中有个地方超内存了,找了老半天才发现。标记应该在没入队之前标记。开始还想用A*算法写的,感觉很麻烦,而且后来也没写出来。BFS和DFS之间还是有很大区别的,坐标范围不是很大最好用BFS,深度很大最好用DFS。

以下是AC代码:

#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;struct p{    int x,y,z,step;};int map[55][55][55];int vis[55][55][55];int xx[]= {-1,1,0,0,0,0};int yy[]= {0,0,-1,1,0,0};int zz[]= {0,0,0,0,-1,1};int tim,a,b,c,t,k;queue<p> q;bool inmap(p pp){    if(pp.x<0||pp.x>=a||pp.y<0||pp.y>=b||pp.z<0||pp.z>=c)        return false;    else        return true;}int min(int x,int y){    return x>y?y:x;}void bfs(){    p s;    s.x=0,s.y=0,s.z=0,s.step=0;    vis[0][0][0]=1;    //map[0][0][0]=1;    while(!q.empty()) q.pop();    q.push(s);    p tp,np;    while(!q.empty())    {        tp=q.front();        q.pop();        //vis[tp.x][tp.y][tp.z]=1;//出队时才标记会使得以前重复进队        if(tp.x==(a-1)&&tp.y==(b-1)&&tp.z==(c-1))        {            tim=min(tim,tp.step);            continue;        }        for(int i=0; i<6; i++)        {            np.x=tp.x+xx[i],np.y=tp.y+yy[i],np.z=tp.z+zz[i];            if(inmap(np)&&!map[np.x][np.y][np.z]&&!vis[np.x][np.y][np.z])            {                np.step=tp.step+1;                //vis[np.x][np.y][np.z]=1;//入队之前标记                map[tp.x][tp.y][tp.z]=1;                q.push(np);            }        }    }}int main(){    scanf("%d",&k);    while(k--)    {        scanf("%d%d%d%d",&a,&b,&c,&t);        for(int i=0; i<a; i++) //x            for(int j=0; j<b; j++) //y                for(int z=0; z<c; z++) //z                {                    scanf("%d",&map[i][j][z]);                }        if(map[a-1][b-1][c-1]==1)        {            printf("-1\n");            continue;        }        if(a+b+c-3>t)        {            printf("-1\n");            continue;        }        tim=1005;        memset(vis,0,sizeof(vis));        //vis[0][0][0]=1;        bfs();        if(tim<=t)            printf("%d\n",tim);        else            printf("-1\n");    }    return 0;}

第二题:

题意:找一组满足条件的数,使得任意两个相邻的数的和为素数。

简单的DFS+回溯

AC代码:

#include<iostream>#include<cstdio>#include<cmath>int n;int vis[20];int q[20];bool prim(int ans){    for(int i=2; i<=sqrt(1.0*ans); i++)    {        if(ans%i==0)            return 0;    }    return 1;}void dfs(int p,int st){    if(st==n&&prim(p+1))    {        for(int i=1; i<n; ++i)        {            printf("%d ",q[i]);        }        printf("%d\n",q[n]);        return ;    }    for(int j=2; j<=n; ++j)    {        if(!vis[j]&&prim(j+p))        {            vis[j]=1;            q[++st]=j;            dfs(j,st);            vis[j]=0;            st--;        }    }}int main(){    int count=1;    while(scanf("%d",&n)!=EOF)    {        printf("Case %d:\n",count);        q[1]=1;        dfs(1,1);        printf("\n");        count++;    }    return 0;}

第三题:

题意:有7种积木。每次按一定顺序输入10个积木,使得堆积成m*n的矩形。

思路:大模拟。用一个数组box【】存没列已经存在的方块数,每次dfs()满足两个条件:1从左到右,能放下。2.box【】.满足放的条件,box【i】之间存在一定的关系,横竖都要与n,m相比较。注意每种积木可能有多种放的形式。

写了两天了,最后还是没发现那里错了。

好像只有两处区别:

1.我用ans标记,比用dfs函数返回麻烦点。

2.每次在与m比较时,我只用一个比较。

别人AC的代码:

 #include <cstdio> #include <cstring> #include <cstdlib>  char tet[20];   //记录方块的下降次序 int box[45];    //把方块分成小格子,记录每列有多个小格子 int m, n;  bool DFS( int cur ) {     if ( cur == 10 ) return true;      switch( tet[cur] )     {         case 'I' :         for ( int i = 0; i < n; i++ )         {             if ( box[i] + 4 <= m )   //判断能不能竖着放             {                 box[i] += 4;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 4;             }             if ( i + 3 < n && box[i] == box[i + 1] && box[i + 1] == box[i + 2] && box[i + 2] == box[i + 3] && box[i] + 1 <= m )    //能不能横着放             {                 for ( int j = i; j < i + 4; j++ ) ++box[j];                 if ( DFS( cur + 1 ) ) return true;                 for ( int j = i; j < i + 4; j++ ) --box[j];             }         }         break;          case 'O':         for ( int i = 0; i < n; i++ )         {             if ( i + 1 < n && box[i] == box[i + 1] && box[i] + 2 <= m )             {                 box[i] += 2;                 box[i + 1] += 2;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 2;                 box[i + 1] -= 2;             }         }         break;          case 'L' :         for ( int i = 0; i < n; i++ )         {             if ( i + 1 < n && box[i] + 3 <= m && box[i] == box[i + 1] )    //正着放L             {                 box[i] += 3;                 box[i + 1] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 3;                 box[i + 1] -= 1;             }              if (i + 2 < n && box[i] + 1 == box[i + 1] && box[i + 1] == box[i + 2] && box[i] + 2 <= m && box[i + 1] + 1 <= m )    //顺时针旋转90°             {                 box[i] += 2;                 box[i + 1] += 1;                 box[i + 2] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 2;                 box[i + 1] -= 1;                 box[i + 2] -= 1;             }              if (i + 1 < n && box[i] + 1 <= m && box[i + 1] + 3 <= m && box[i + 1] + 2 == box[i] )    //顺时针旋转180°             {                 box[i] += 1;                 box[i + 1] += 3;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 1;                 box[i + 1] -= 3;             }              if (i + 2 < n && box[i] == box[i + 1] && box[i + 1] == box[i + 2] && box[i + 2] + 2 <= m )    //顺时针旋转270°             {                 box[i] += 1;                 box[i + 1] += 1;                 box[i + 2] += 2;                 if ( DFS(cur + 1) ) return true;                 box[i] -= 1;                 box[i + 1] -= 1;                 box[i + 2] -= 2;             }          }         break;          case 'J' :         for ( int i = 0; i < n; i++ )         {             if (i + 1 < n && box[i] == box[i + 1] && box[i + 1] + 3 <= m )         //0             {                 box[i] += 1;                 box[i + 1] += 3;                 if ( DFS(cur + 1) ) return true;                 box[i] -= 1;                 box[i + 1] -= 3;             }             if (i + 2 < n && box[i] == box[i + 1] && box[i + 1] == box[i + 2] && box[i] + 2 <= m)         //90             {                 box[i] += 2;                 box[i + 1] += 1;                 box[i + 2] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 2;                 box[i + 1] -= 1;                 box[i + 2] -= 1;             }             if (i + 1 < n && box[i] + 2 == box[i + 1] && box[i] + 3 <= m && box[i + 1] + 1 <= m )         //180             {                 box[i] += 3;                 box[i + 1] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 3;                 box[i + 1] -= 1;             }             if (i + 2 < n && box[i] == box[i + 1] && box[i + 2] + 1 == box[i + 1] && box[i] + 1 <= m && box[i + 2] + 2 <= m)         //270             {                 box[i] += 1;                 box[i + 1] += 1;                 box[i + 2] += 2;                 if ( DFS(cur + 1) ) return true;                 box[i] -= 1;                 box[i + 1] -= 1;                 box[i + 2] -= 2;             }         }         break;          case 'Z' :         for ( int i = 0; i < n; i++ )         {             if (i + 2 < n && box[i + 2] == box[i + 1] && box[i + 1] + 1 == box[i] && box[i] + 1 <= m && box[i + 1] + 2 <= m )  //0             {                 box[i] += 1;                 box[i + 1] += 2;                 box[i + 2] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 1;                 box[i + 1] -= 2;                 box[i + 2] -= 1;             }             if (i + 1 < n && box[i] + 1 == box[i + 1] && box[i] + 2 <= m && box[i + 1] + 2 <= m)   //90             {                 box[i] += 2;                 box[i + 1] += 2;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 2;                 box[i + 1] -= 2;             }         }         break;          case 'S' :         for ( int i = 0; i < n; i++ )         {             if (i + 2 < n && box[i] == box[i + 1] && box[i + 1] + 1 == box[i + 2] && box[i + 1] + 2 <= m && box[i + 2] + 1 <= m )    //0             {                 box[i] += 1;                 box[i + 1] += 2;                 box[i + 2] += 1;                 if ( DFS(cur + 1) ) return true;                 box[i] -= 1;                 box[i + 1] -= 2;                 box[i + 2] -= 1;             }             if (i + 1 < n && box[i + 1] + 1 == box[i] && box[i] + 2 <= m && box[i + 1] + 2 <= m )    //90             {                 box[i] += 2;                 box[i + 1] += 2;                 if ( DFS(cur + 1) ) return true;                 box[i] -= 2;                 box[i + 1] -= 2;             }         }         break;          case 'T' :         for ( int i = 0; i < n; i++ )         {             if ( i + 2 < n && box[i] == box[i + 1] && box[i + 1] == box[i + 2] && box[i + 1] + 2 <= m ) //0             {                 box[i] += 1;                 box[i + 1] += 2;                 box[i + 2] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 1;                 box[i + 1] -= 2;                 box[i + 2] -= 1;             }              if ( i + 1 < n && box[i] + 1 == box[i + 1] && box[i] + 3 <= m ) //90             {                 box[i] += 3;                 box[i + 1] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 3;                 box[i + 1] -= 1;             }             if ( i + 2 < n && box[i] == box[i + 2] && box[i + 1] + 1 == box[i] && box[i + 1] + 2 <= m ) //180             {                 box[i] += 1;                 box[i + 1] += 2;                 box[i + 2] += 1;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 1;                 box[i + 1] -= 2;                 box[i + 2] -= 1;             }              if ( i + 1 < n && box[i + 1] + 1 == box[i] && box[i + 1] + 3 <= m ) //270             {                 box[i] += 1;                 box[i + 1] += 3;                 if ( DFS( cur + 1 ) ) return true;                 box[i] -= 1;                 box[i + 1] -= 3;             }         }         break;     }     return false; }  int main() {     while ( scanf( "%d%d", &n, &m ), n || m )     {         for ( int i = 0; i < 10; i++ )         {             getchar();             tet[i] = getchar();         }          memset( box, 0, sizeof(box) );          if ( DFS(0) ) puts("Yes");         else puts("No");     }     return 0; }

我的代码:

#include<cstdio>#include<cstring>#include<cstdlib>int n,m,ans;char sign[20];int box[45];void dfs(int st){    if(st==10)    {        ans=1;return ;    }    switch(sign[st])    {        case 'I':        for(int i=0;i<n;i++)        {            //竖着放            if(box[i]+4<=m)            {                box[i]+=4;                dfs(++st);                if(ans)                return ;                box[i]-=4;            }            //横着放            if((i+3<n)&&(box[i]+1<=m)&&(box[i]==box[i+1])&&(box[i+1]==box[i+2])&&(box[i+2]==box[i+3]))            {                box[i]++,box[i+1]++,box[i+2]++,box[i+3]++;                dfs(++st);                if(ans)                return ;                box[i]--,box[i+1]--,box[i+2]--,box[i+3]--;            }        }        break;        case 'J'://改到这里来了        for(int i=0;i<n;i++)        {            //0度            if((i+2)<n&&(box[i]==box[i+1])&&(box[i+1]==box[i+2])&&(box[i]+2<=m))            {                box[i]+=2,box[i+1]++,box[i+2]++;                dfs(++st);                if(ans)                return ;                box[i]-=2,box[i+1]--,box[i+2]--;            }            //90度            if((i+1)<n&&(box[i]+3<=m)&&(box[i]+2==box[i+1]))            {                box[i]+=3,box[i+1]++;                dfs(++st);                if(ans)                return ;                box[i]-=3,box[i+1]--;            }            //180度            if((i+2)<n&&(box[i]==box[i+1])&&(box[i+1]-1==box[i+2]&&(box[i]+1<=m)))            {                box[i]++,box[i+1]++,box[i+2]+=2;                dfs(++st);                if(ans)                return ;                box[i]--,box[i+1]--,box[i+2]-=2;            }            //270度            if((i+1)<n&&(box[i]==box[i+1])&&(box[i+1]+3<=m))            {                box[i]+=1,box[i+1]+=3;                dfs(++st);                if(ans)                return ;                box[i]--,box[i+1]-=3;            }        }        break;        case 'L':        for(int i=0;i<n;i++)        {            //0            if((i+1<n)&&(box[i]==box[i+1])&&(box[i]+3<=m))            {                box[i]+=3,box[i+1]++;                dfs(++st);                if(ans)                return ;                box[i]-=3,box[i+1]--;            }            //90            if((i+2<n)&&(box[i]+1==box[i+1])&&(box[i+1]==box[i+2])&&(box[i]+2<=m))            {                box[i]+=2,box[i+1]++,box[i+2]++;                dfs(++st);                if(ans)                return ;                box[i]-=2,box[i+1]--,box[i+2]--;            }            //180            if((i+1<n)&&(box[i+1]+2==box[i])&&(box[i]+1<=m))            {                box[i]++,box[i+1]+=3;                dfs(++st);                if(ans)                return ;                box[i]--,box[i+1]-=3;            }            //270            if((i+2<n)&&(box[i]==box[i+1])&&box[i+1]==box[i+2]&&box[i+2]+2<=m)            {                box[i]++,box[i+1]++,box[i+2]+=2;                dfs(++st);                if(ans)                return ;                box[i]--,box[i+1]--,box[i+2]-=2;            }        }        break;        case 'O':            for(int i=0;i<n;i++)            {                if((i+1)<n&&box[i]==box[i+1]&&box[i]+2<=m)                {                    box[i]+=2,box[i+1]+=2;                    dfs(++st);                    if(ans)                    return ;                    box[i]-=2,box[i+1]-=2;                }            }        break;        case 'S':            //0            for(int i=0;i<n;i++)            {                if(i+2<n&&box[i]==box[i+1]&&box[i+1]+1==box[i+2]&&box[i+1]+2<=m)                {                    box[i]++,box[i+1]+=2,box[i+2]++;                    dfs(++st);                    if(ans)                    return ;                    box[i]--,box[i+1]-=2,box[i+2]--;                }            }            //90            for(int i=0;i<n;i++)            {                if(i+1<n&&box[i+1]+1==box[i]&&box[i]+2<=m)                {                    box[i]+=2,box[i+1]+=2;                    dfs(++st);                    if(ans)                    return ;                    box[i]-=2,box[i+1]-=2;                }            }        break;        case 'T':            for(int i=0;i<n;i++)            {                //0                if(i+2<n&&box[i]==box[i+1]&&box[i+1]==box[i+2]&&box[i+1]+2<=m)                {                    box[i]++,box[i+1]+=2,box[i+2]++;                    dfs(++st);                    if(ans)                    return ;                    box[i]--,box[i+1]-=2,box[i+2]--;                }                //90                if(i+1<n&&box[i]+1==box[i+1]&&box[i]+3<=m)                {                    box[i]+=3,box[i+1]++;                    dfs(++st);                    if(ans)                    return ;                    box[i]-=3,box[i+1]--;                }                //180                if(i+2<n&&box[i]-1==box[i+1]&&box[i+1]+1==box[i+2]&&box[i]+1<=m)                {                    box[i]++,box[i+1]+=2,box[i+2]++;                    dfs(++st);                    if(ans)                    return ;                    box[i]--,box[i+1]-=2,box[i+2]--;                }                //270                if(i+1<n&&box[i]-1==box[i+1]&&box[i+1]+3<=m)                {                    box[i]++,box[i+1]+=3;                    dfs(++st);                    if(ans)                    return ;                    box[i]--,box[i+1]-=3;                }            }        break;        case 'Z':            for(int i=0;i<n;i++)            {                //0                if(i+2<n&&box[i]-1==box[i+1]&&box[i+1]==box[i+2]&&box[i]+1<=m)                {                    box[i]++,box[i+1]+=2,box[i+2]++;                    dfs(++st);                    if(ans)                    return ;                    box[i]--,box[i+1]-=2,box[i+2]--;                }                //90                if(i+1<n&&box[i]+1==box[i+1]&&box[i+1]+2<=m)                {                    box[i]+=2,box[i+1]+=2;                    dfs(++st);                    if(ans)                    return ;                    box[i]-=2,box[i+1]-=2;                }            }        break;    }}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        if(m==0&&n==0) break;        for(int i=0;i<10;i++)        {            getchar();            //scanf("%c",&sign[i]);            sign[i]=getchar();        }        //for(int i=0;i<10;i++)        //putchar(sign[i]);        memset(box,0,sizeof(box));        ans=0;        dfs(0);        if(ans==1)        printf("Yes");        else        printf("No");    }    return 0;}

第四题:

题意:单源起点,终点分为两种,找最短路。

思路:最短路,n比较小,直接用三个for就OK了,貌似dijskal啥的都忘记了,看来得花时间复习下了。

AC代码:

#include<stdio.h>#define maxn 11#define INF 0x7fffffffint p[maxn];int road[maxn][maxn];int n,m,s,l;int fmin(int x,int y){    return x>y?y:x;}void init(){    for(int ii=0; ii<n; ii++)    {        for(int jj=0; jj<n; jj++)        {            if(ii==jj)            {                road[ii][jj]=0;                //road[jj][ii]=0;            }            else            {                road[ii][jj]=INF;                //road[jj][ii]=INF;            }        }    }}void prim(){    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)        {            for(int k=0; k<n; k++)            {                if(road[i][k]!=INF&&road[k][j]!=INF)                {                    road[i][j]=fmin(road[i][j],road[i][k]+road[k][j]);                }            }        }}int main(){    while(scanf("%d",&n)!=EOF)    {        init();        for(int i=0; i<n; i++)        {            scanf("%d%d",&m,&p[i]);            for(int j=0; j<m; j++)            {                scanf("%d%d",&s,&l);                road[i][s]=l;                road[s][i]=l;            }        }        prim();        int min=INF;        for(int i=0; i<n; i++)        {            //printf("%d\n",p[i]);            if(p[i]==1&&road[0][i]!=INF)            {                //printf("%d\n",road[0][i]);                min=fmin(road[0][i],min);            }        }        printf("%d\n",min);    }    return 0;}

第五题:

题意:从一堆数中找出最多的一组数,是得任意的两个数互相不被整除。

思路:看了很多人写的,有用二分图匹配的,不过想在还不会。也有用暴力写的,其实应该早就想到暴力,因为数据不是很大。遍历一次,找出以每个数开头的与它相互乘除的数个总个数,并标记这些数,用个二维数组就行了。然后每次找最小的以某个数开头的数组,标记这些数,并且ans++。直到所有的数都被标记完。

AC代码:

#include<iostream>using namespace std;#define MAXN 1001__int64 a[MAXN];int map[MAXN][MAXN];bool flag[MAXN];//标记使用int n;int main (){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i = 1;i <= n;++i)            scanf("%I64d",&a[i]);        memset(map,0,sizeof(map));        for(int i = 1;i <= n;++i)            for(int j = 1;j <= n;++j)                if (a[i] % a[j] == 0 || a[j] % a[i] == 0)                {                    map[i][j] = 1;                    map[i][0]++;                }        int cnt = 0;        for(int i = 1;i <= n;++i)            flag[i] = true;        while(1)        {            int pos = -1,minvalue = 100000;            for(int i = 1;i <= n;++i)            {                if(map[i][0] < minvalue && flag[i])                {                    pos = i;                    minvalue = map[i][0];                }            }            if (pos == -1)                break;            cnt++;            //cout<<"pos:"<<pos<<endl;            flag[pos] = 0;            for(int i = 1;i <= n;++i)                if (map[pos][i] == 1)                    flag[i] = 0;        }        printf("%d\n",cnt);    }    return 0;}

第六题:

题意:找规律,模拟题。

思路:其实就是输入一个16进制的数,然后按一定规律输出,比赛时想到了,但太紧张,写的不好,就没写了。

AC代码:

#include<cstdio>#define maxn 1000int t,c,a;int map[maxn][maxn];void init(){    for(int i=0;i<c;i++)    {        for(int j=0;j<5;j++)        {            scanf("%x",&a);            for(int k=0;k<8;k++)            {                if(a%2==1)                {                    map[k][6*i+j]=1;                }                else                map[k][6*i+j]=0;                a/=2;            }        }        if(i!=(c-1))        for(int k=0;k<8;k++)        map[k][5+6*i]=0;    }}void output(){    int flag=0;    for(int i=0;i<8;i++)    {        for(int j=0;j<(6*c-1);j++)        {            if(i==7&&map[i][j]==0)            {                flag=1;                break;            }            if(map[i][j]==1)            printf("#");            else            printf(" ");        }        if(flag==0)        printf("\n");    }}int main(){    scanf("%d",&t);    for(int i=1;i<=t;i++)    {        scanf("%d",&c);        init();        printf("Case %d:\n",i);        printf("\n");        output();        printf("\n");    }    return 0;}