1119 Collecting Coins 湖南省第八届

来源:互联网 发布:域名注册服务商查询 编辑:程序博客网 时间:2024/05/19 21:18

120MS   AC

看过别人的代码,看过比他短的,但是也有一百多行,像这种长代码的,如果说是学模仿别人的代码,意义实在不大,如果等级不过还不如去做一些简单的搜索,先练练后面再做;关键还是注意事项,我也是看了别人的注意事项才改出来的;

大致思路:

1,以DFS为主板,因为石头就5个,像求全排列一样写,时间复杂度  5!*4*4*4*4*4;5!是石头排列的种类,4*4*4*4*4是每个石头分别有四种方向;128840

2,有时候不推石头比推石头得到的钱更多;

3.用BFS询问,石头能不能被推动;

4,每次推完石头,用BFS先把可以拣到的钱全部拣了,标记为空地,这里最关键,实力不行我整整思考了一天,这里我用到hh[7][22]记录每层改变的位置,当返回的时候你是要返回去的;

5,最后比较每种情况输去的最大值

 

 

 

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include <queue>
using namespace std;
int N,M,l,w,sum,cp,num;
char a[22][22];
int b[22];
int fx[4][2]={1,0,0,1,-1,0,0,-1};
struct point
{
    int x,y;
}hh[7][22],ff[22],head,tail;
int bd(int x1,int y1)
{
    if(x1<0||y1<0||x1>=N||y1>=M)
        return 1;
    return 0;
 
}
int bfs1(int kk,int kkk,int f,int f1)\\是否将石头推动
{
    if(kk==f&&kkk==f1)
        return 1;
    queue<point>q;
    head.x=kk;
    head.y=kkk;
    q.push(head);
    int i,j;
    int c[14][14];
    for(i=0;i<=12;i++)
        for(j=0;j<=12;j++)
        c[i][j]=1;
    c[kk][kkk]=0;
    while(!q.empty())
    {
        head=q.front();
        q.pop();
        for(i=0;i<4;i++)
        {
            tail.x=head.x+fx[i][0];
            tail.y=head.y+fx[i][1];
           if(tail.x<0||tail.y<0||tail.x>=N||tail.y>=M)
            continue;
         if(a[tail.x][tail.y]=='X'||a[tail.x][tail.y]=='O')
            continue;
            if(c[tail.x][tail.y])
            {
                c[tail.x][tail.y]=0;
                if(tail.x==f&&tail.y==f1)
                    return 1;
               q.push(tail);
            }
        }
    }
    return 0;
}
int  bfs(int l1,int l2,int ll)\\将可以拣的钱,全部拣了
{
    queue<point>q;
    head.x=l1;
    head.y=l2;
    q.push(head);
    int i,j;
    int c[22][22];
    for(i=0;i<=20;i++)
        for(j=0;j<=20;j++)
        c[i][j]=1;
    c[l1][l2]=0;
    int fff1=0;
    while(!q.empty())
    {
        head=q.front();
        q.pop();
        for(i=0;i<4;i++)
        {
            tail.x=head.x+fx[i][0];
            tail.y=head.y+fx[i][1];
           if(tail.x<0||tail.y<0||tail.x>=N||tail.y>=M)
            continue;
         if(a[tail.x][tail.y]=='X'||a[tail.x][tail.y]=='O')
            continue;
            if(c[tail.x][tail.y])
            {
                c[tail.x][tail.y]=0;
               if(a[tail.x][tail.y]=='C')
               {
                   hh[ll][fff1].x=tail.x;
                   hh[ll][fff1].y=tail.y;
                    fff1++;
                    a[tail.x][tail.y]='.';
               }
               q.push(tail);
            }
        }
    }
    return fff1;
}
void hs(int fff1,int ll)
{
    for(int i=0;i<fff1;i++)
        a[hh[ll][i].x][hh[ll][i].y]='C';
}
void dfs(int kk,int kkk,int gg)\\全摆列  当石头为5时一共128840种不同情况
{
    int i,j;
    int x1,y1,x2,y2;
    int sum1;
 
     if(cp==sum)
     return;
     if(gg>cp)
        cp=gg;
     for(i=0;i<num;i++)
     {
         if(!b[i])continue;
            b[i]=0;
           for(j=0;j<4;j++)
       {
         x1=ff[i].x+fx[j][0];
         y1=ff[i].y+fx[j][1];
         x2=ff[i].x-fx[j][0];
         y2=ff[i].y-fx[j][1];
         if(x1<0||y1<0||x1>=N||y1>=M)
            continue;
         if(a[x2][y2]=='X'||a[x2][y2]=='C'||a[x2][y2]=='O'||bd(x2,y2))
            continue;
            if(a[x1][y1]=='X'||a[x1][y1]=='O')
                continue;
            if(bfs1(kk,kkk,x1,y1))
            {
                a[ff[i].x][ff[i].y]='.';
                a[x2][y2]='X';
                sum1=bfs(ff[i].x,ff[i].y,i);
                dfs(ff[i].x,ff[i].y,gg+sum1);
                hs(sum1,i);                \\我就是错在这里
                a[ff[i].x][ff[i].y]='O';
                a[x2][y2]='.';
             }
          }
         b[i]=1;
 
     }
}
int main()
{
     int T,i,j;
     scanf("%d",&T);
     while(T--)
     {
 
         cp=0;
         num=0;
         sum=0;
        scanf("%d%d",&N,&M);
        for(i=0;i<N;i++)
        {
        scanf("%s",a[i]);
        for(j=0;j<M;j++)
        {
            if(a[i][j]=='C')
            sum++;
            if(a[i][j]=='S')
            l=i,w=j;
            if(a[i][j]=='O')
            {
                ff[num].x=i;
                ff[num].y=j;
                num++;
            }
        }
        }
       for(i=0;i<=20;i++)
        b[i]=1;
        cp=bfs(l,w,6);
        if(cp!=sum)//当已经将石头拣完就不拣了 算是剪枝
        dfs(l,w,cp);
        printf("%d\n",cp);
     }
}

0 0
原创粉丝点击