首页 > 代码库 > [水+思路] hdu 3682 To Be an Dream Architect

[水+思路] hdu 3682 To Be an Dream Architect

题意:

就是有n*n*n个木块,然后给你m条三维的直线

问这些直线能够消掉多少个木块

思路:

其实就是求m条直线有几个交点

然后就是一个双重循环解决

然后读入的时候需要判重

用三个1000*1000的数组来实现。

注意

3 3

Y=2,Z=2

X=2,Y=2

X=2,Z=2

答案应该是7而不是6,因为三条线交在同一点上。

6的原因是在判断第一条线的时候 和后面两个都有交点,但是交点是同一个 其实只有1个。

这里的判重方法就是,用这条线没有的那个坐标进行判重。

因为对于Y=2,Z=2 交点的话只有X坐标不确定,所以用X坐标来判重。

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
int map[22][22];
int move[8][2]= {{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1}};
int n;
struct winpoint
{
    int cnt,x,y;
    winpoint()
    {
        cnt=x=y=0;
    }
};
int dfs(int x,int y,int f,int key)
{
    int xx=x,yy=y;
    int sum=0;
    while(1)
    {
        sum++;
        xx+=move[f][0];
        yy+=move[f][1];
        if(xx<0||yy<0||xx>=15||yy>=15) break;
        if(map[xx][yy]!=key) break;
    }
    return sum;
}
winpoint ok1(int key)
{
    winpoint ans;
    for(int i=0; i<15; i++)
    {
        for(int j=0; j<15; j++)
        {
            if(map[i][j]!=-1) continue;
            int f=0;
            for(int k=0; k<4; k++)
            {
                if(dfs(i,j,k,key)+dfs(i,j,k+4,key)-1>=5) f=1;
                if(f) break;
            }
            if(f)
            {
                if(ans.cnt==0)
                {
                    ans.x=i;
                    ans.y=j;
                }
                ans.cnt++;
            }
        }
    }
    return ans;
}
int main()
{
    while(scanf("%d",&n),n)
    {
        memset(map,-1,sizeof(map));
        int f=-1;
        int bl,wh;
        bl=wh=0;
        while(n--)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            map[x][y]=z;
            if(z) bl++;
            else wh++;
        }
        /*for(int i=0;i<15;i++)
        {
            for(int j=0;j<15;j++)
            {
                if(map[i][j]==-1) printf(".");
                else printf("%d",map[i][j]);
            }
            puts("");
        }*/
        if(bl<wh||bl>=wh+2)   //不合法
        {
            puts("Invalid.");
            continue;
        }
        int key;
        if(bl==wh) key=1;
        else key=0;
        winpoint ans;
        ans=ok1(key);

        if(ans.cnt>=1)   //一步直接赢
        {
            printf("%s",key?"Place black ":"Place white ");
            printf("at (%d,%d) to win in 1 move.\n",ans.x,ans.y);
            continue;
        }
        ans=ok1(key^1);
        if(ans.cnt>=2)   //两个必胜点 直接输
        {
            puts("Lose in 2 moves.");
            continue;
        }
        if(ans.cnt==1)   //填对方必胜点 看能否赢
        {
            map[ans.x][ans.y]=key;
            winpoint tep=ok1(key);
            if(tep.cnt>=2) //对方堵不住 直接赢
            {
                printf("%s",key?"Place black ":"Place white ");
                printf("at (%d,%d) to win in 3 moves.\n",ans.x,ans.y);
                continue;
            }
            else   //不能则不分胜负
            {
                puts("Cannot win in 3 moves.");
                continue;
            }
        }
        for(int i=0; i<15; i++)
        {
            for(int j=0; j<15; j++)
            {
                if(map[i][j]!=-1) continue;
                map[i][j]=key;
                winpoint tep=ok1(key);
                if(tep.cnt>=2)
                {
                    printf("%s",key?"Place black ":"Place white ");
                    printf("at (%d,%d) to win in 3 moves.\n",i,j);
                    f=1;
                }
                if(f==1) break;
                map[i][j]=-1;
            }
            if(f==1) break;
        }
        if(f==-1) puts("Cannot win in 3 moves.");
    }
    return 0;
}



[水+思路] hdu 3682 To Be an Dream Architect