JZOJ4824 配对游戏

题目:流行的跳棋游戏是在一个有m*n个方格的长方形棋盘上玩的。棋盘起初全部被动物或障碍物占满了。在一个方格中,‘X’表示一个障碍物,一个‘0’~‘9’的个位数字表示一个不同种类的动物,相同的个位数字表示相同种类的动物。一对动物只有当它们属于同一种类时才可以被消去。消去之后,他们所占的方格就成为空方格,直到游戏结束。要消去一对动物的前提条件是:这对候选动物所在的方格必须相邻,或它们之间存在一条通路。棋盘上一个方格只和其上下左右的方格相邻。一条通路是由一串相邻的空方格组成。路的长度则是通路中空方格的数目。你要输出可被消去的动物的最多对数,以及在此操作过程中,最小的通路长度总和。

Input

输入文件第一行包含二个整数 m和n,中间用一个空格隔开,其中1<=m,n<=5。接下来的m行,每一行有n个字符,每个字符是’X’,’0’,’1’,…,’9’其中的一个。相邻两个字符间没有空格。

Output

输出文件仅有一行包含两个整数,中间用一个空格隔开。第一个整数是可被消去的动物的最多对数。第二个整数是消去这些动物对的过程中,最小的通路长度总和。

Sample Input

3 4
XX0X
X11X
X0XX

Sample Output

2 2

Data Constraint

N,M<=5
超级恶心的暴力题目,各种估价函数好,可惜我不会估价函数,只能学习WerKeyTom—FTD的打法,打了6000多byte。就是暴力搜索所有状态然后扩展,我的哥啊,为了一个readln调试了1个小时,神TM,靠。以后一定记住读入char一定换行啊我的哥,要死喽。。

uses math;
type node=record
        x,y,z:longint;
end;
const big=20000000;
var
        i,j,k,n,m,tot,ans1,ans2,xx,yy:longint;
        a:Array[0..30]of node;
        hash:Array[0..big,0..2]of longint;
        f1:Array[0..30,0..3]of longint;
        f:Array[0..10,0..10]of longint;
        pd,vis:array[0..10,0..10]of boolean;
        bz:array[0..30]of boolean;
        ch:char;
procedure qsort(l,r:longint);
var
        i,j,m:longint;
        t:node;
begin
        i:=l;
        j:=r;
        m:=a[(l+r)div 2].z;
        repeat
                while a[i].z<m do inc(i);
                while a[j].z>m do dec(j);
                if i<=j then
                begin
                        t:=a[i];
                        a[i]:=a[j];
                        a[j]:=t;
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qsort(l,j);
        if i<r then qsort(i,r);
end;
function work(x,y:longint):longint;
var
        head,tail,i,j:longint;
begin
        head:=0;
        tail:=1;
        for i:=1 to n do
        for j:=1 to m do
        vis[i,j]:=not pd[i,j];
        for i:=0 to max(n+1,m+1) do
        begin
                vis[0,i]:=true;
                vis[i,0]:=true;
                vis[i,m+1]:=true;
                vis[n+1,i]:=true;
        end;
        f1[1,0]:=a[x].x;
        f1[1,1]:=a[x].y;
        f1[1,2]:=0;
        vis[a[x].x,a[x].y]:=true;
        while head<tail do
        begin
                inc(head);
                i:=f1[head,0];
                j:=f1[head,1];
                if (i=a[y].x)and(j=a[y].y) then exit(f1[head,2]-1);
                if not vis[i-1,j] then
                begin
                        vis[i-1,j]:=true;
                        inc(tail);
                        f1[tail,0]:=i-1;
                        f1[tail,1]:=j;
                        f1[tail,2]:=f1[head,2]+1;
                end;
                if not vis[i+1,j] then
                begin
                        vis[i+1,j]:=true;
                        inc(tail);
                        f1[tail,0]:=i+1;
                        f1[tail,1]:=j;
                        f1[tail,2]:=f1[head,2]+1;
                end;
                if not vis[i,j+1] then
                begin
                        vis[i,j+1]:=true;
                        inc(tail);
                        f1[tail,0]:=i;
                        f1[tail,1]:=j+1;
                        f1[tail,2]:=f1[head,2]+1;
                end;
                if not vis[i,j-1] then
                begin
                        vis[i,j-1]:=true;
                        inc(tail);
                        f1[tail,0]:=i;
                        f1[tail,1]:=j-1;
                        f1[tail,2]:=f1[head,2]+1;
                end;
        end;
        exit(-1);
end;
function g(x,y:longint):longint;
begin
        exit((x-1)*m+y-1);
end;
function check(x:longint):longint;
var
        k:longint;
begin
        k:=x mod big;
        if k=0 then k:=big;
        while (hash[k,0]<>0) and(hash[k,0]<>x)do k:=k mod big+1;
        exit(k);
end;
procedure dg(x,y1,y2,y:longint);
var
        x3,y3,i,j,k,lon:longint;
begin
    if (ans1=tot div 2)and(ans2=0)then exit;
    if (y1>ans1)then
    begin
        ans1:=y1;
        ans2:=y2;
    end
    else if (y1=ans1)and(y2<ans2)then ans2:=y2;
    x3:=0;
    y3:=0;
    k:=check(y);
    if (y<>0)and(hash[k,0]=y)then
    begin
        if (y1+hash[k,1]>ans1)then
        begin
            ans1:=y1+hash[k,1];
            ans2:=y2+hash[k,2];
        end
        else if (y1+hash[k,1]=ans1)and(y2+hash[k,2]<ans2)then ans2:=y2+hash[k,2];
        xx:=hash[k,1];
        yy:=hash[k,2];
        exit;
    end;
    for i:=1 to tot-1 do
        if (not bz[i])then
        for j:=i+1 to tot do
        begin
                if (bz[j])then continue;
                if (a[j].z<>a[i].z)then break;
                pd[a[i].x,a[i].y]:=true;
                pd[a[j].x,a[j].y]:=true;
                lon:=work(i,j);
                if (lon>=0)then
                begin
                    bz[i]:=true;
                    bz[j]:=true;
                    if (x3<x div 2)or((x3=x div 2)and(lon<y3))then
                        dg(x-2,y1+1,y2+lon,y+(1<<g(a[i].x,a[i].y))+(1<<g(a[j].x,a[j].y)));
                    if (xx+1>x3)then
                    begin
                        x3:=xx+1;
                        y3:=yy+lon;
                    end
                    else if (xx+1=x3)and(yy+lon<y3)then y3:=yy+lon;
                    bz[i]:=false;
                    bz[j]:=false;
                end;
                pd[a[i].x,a[i].y]:=false;
                pd[a[j].x,a[j].y]:=false;
                if (x3=x div 2)and(y3<=3)then
                begin
                    k:=check(y);
                    hash[k,0]:=y;
                    hash[k,1]:=x3;
                    hash[k,2]:=y3;
                    xx:=x3;
                    yy:=y3;
                    exit;
                end;
            end;
    k:=check(y);
    hash[k,0]:=y;
    hash[k,1]:=x3;
    hash[k,2]:=y3;
    xx:=x3;
    yy:=y3;
end;
begin
        assign(input,'pair.in');
        assign(output,'pair.out');
        reseT(input);
        rewrite(output); 
        readln(n,m);
        for i:=1 to n do
        begin
                for j:=1 to m do
                begin
                        read(ch);
                        if ch='X' then f[i,j]:=-1
                        else begin
                                f[i,j]:=ord(ch)-48;
                                inc(tot);
                                a[tot].x:=i;a[tot].y:=j;
                                a[tot].z:=f[i,j];
                        end;
                end;
                readln;
        end;

        qsort(1,tot);
        dg(tot,0,0,0);
        if xx>ans1 then
        begin
                ans1:=xx;
                ans2:=yy;
        end
        else if (xx=ans1)and(yy<ans2) then ans2:=yy;
        writeln(ans1,' ',ans2);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值