HUST 1625 Chessboard

1 篇文章 0 订阅
1 篇文章 0 订阅

Chessboard

Time Limit: 1 Sec   Memory Limit: 128 MB
Submissions: 39   Solved: 11

Description

Given an N*N(N<=1000)chessboard where you want to place chess knights.
On this chessboard you have to apply M(M<=100000) operations:

Input

The first line contains a single integer T, the number of test cases.
For each case,
The first line contains integer N, M.
The next M lines contain the operation in following form.
C a b x: place chess knight on cell(a,b), the value of the knight is x. (1<=a,b<=n, 1<=x<=100000)
It grants that cell(a,b) has no knight before the operation.
Q a b: answer the maximum value of knight which is connected with knight(a,b), include itself.
If cell (a,b)has no knight, just answer -1. A knight is directly connected with the knight on the left, 
right,  up  and  down.  Two  knights  are  connected  if  they  have  been  directly  connected  or 
interconnected through some other connected knights.
The initial chessboard is empty.

Output

For each question, output the answer in one line.

Sample Input

1
3 7
C 2 2 1
Q 2 2
C 1 2 2
Q 2 2
C 3 3 3
Q 3 3
Q 1 1

Sample Output

1
2
3
-1

HINT

Source

The 8th(2013) ACM Programming Contest of HUST


#include<iostream>
#include<stdio.h>
using namespace std;
#define maxn 1001

int d[4][2]={0,-1,0,1,-1,0,1,0};
bool num[maxn][maxn];
int N;
struct node{
    int parent;
    int value;
}elem[maxn*maxn];

void init()
{
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
        {
            elem[i*N+j].value=0;
            elem[i*N+j].parent=i*N+j;
            num[i] [j] =0;
        }
}

int Find(int m)
{
    if(elem[m] .parent!=m) return elem[m] .parent=Find(elem[m] .parent);
    return m;
/*
    int root,temp;
    temp=m;
    while(m!=elem[m] .parent)
        m=elem[m] .parent;
    root=m;
    m=temp;
    while(m!=elem[m] .parent)
    {
        temp=elem[m] .parent;
        elem[m] .parent=root;
        m=temp;
    }
    return root;*/
}
void Union(int ax,int bx)
{
    int a,b;
    a=Find(ax);
    b=Find(bx);
    if(elem[a] .value>=elem[b] .value)
    {
        elem[b] .parent=elem[a] .parent;
        //elem[b] .value+=elem[a] .value;
    }
    else
    {
        elem[a] .parent=elem[b] .parent;
//elem[a] .value+=elem[b] .value;
    }
}

void cutin(int x,int y,int n)
{
    elem[x*N+y].value=n;
    num[x] [y] =1;
}

int main()
{
    int T,M;
    char c[2];
    int x,y,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        //cin>>N>>M;
        init();
        for(int i=0;i<M;i++)
        {
            scanf("%s",c);
            if(c[0]=='Q')
            {
                scanf("%d%d",&x,&y);
                //   cin>>x>>y;
                x-=1;
                y-=1;
                if(num[x] [y] ==0) printf("-1\n");
                else
                {
                    int ans=Find(x*N+y);
                    printf("%d\n",elem[ans] .value);                    
// cout<<elem[ans] .value<<endl;
                }

            }
            else if(c[0]=='C')
            {
                scanf("%d%d%d",&x,&y,&n);
                // cin>>x>>y>>n;
                x-=1;y-=1;
                cutin(x,y,n);
                for(int i=0;i<4;i++)
                {
                    int dx=d[i] [0];
                    int dy=d[i] [1];
                    int nx=x+dx;
                    int ny=y+dy;
                    if(0<=nx&&nx<N&&0<=ny&&ny<N&&num[nx] [ny] !=0)
                    {
                        int ax=x*N+y;
                        int bx=nx*N+ny;
                        Union(ax,bx);
                    }
                }
            }
        }
    }
    return 0;
}

方法:

建立一个bool 类型的二维数组 记录 位置是否有数

一个一维数组存并查集 原坐标(i,j),新坐标i*n+j

并查集的模板


第一次写并查集。问了好多的人。最后自己写的TLE了。

问题:

1.数组开小了 之前是maxn<<4 后来改成了maxn*maxn

2.输入输出从c++改成了c  注意的地方是 读char的时候 要设成string类型 不然之前的回车和空格可能会被吃掉

3.find函数改成了递归函数


前两个问题当时写线段树的时候就经常的出现,自己还是没能发现和克服。

最后一个就有点智商捉急了。


感谢死命催了我两天的小伙伴,给了关键思路的小伙伴,最后把程序改正确的小伙伴。

虽然还是很遗憾,没能自己把程序调AC,这个假期的基本目标就是可以自己独立的调试程序。

做题的感觉不错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值