首页 > 代码库 > HDU-2259-Continuous Same Game (2)(BFS+DFS+模拟)

HDU-2259-Continuous Same Game (2)(BFS+DFS+模拟)

Problem Description
After repeated attempts, LL finds the greedy strategy is very awful in practice. Even there is no apparent evidence to proof it is better than a random one. So he has to drop this strategy and try to discover a better one. 
 

Input
There are 100 test cases. Each test case begins with two integers n,m ( 5<=n,m<=20 ), which is the size of the board. Then n lines follow, each contains m characters, indicating the color of the block. There are 5 colors, and each with equal probability.
 

Output
For each test case, first output a single line containing the number of steps S. Then S lines follow, each contains two integers indicating the position of an arbitrary block of the group you want to remove. 

For the i-th test case, let Ai is the total point of your scheme and Bi is the total point of the greedy strategy . Then I will calculate the average of (Ai/Bi), 1<=i<=100. You will get WA if your ouput is invalid or this average is less than 1.5.
 

Sample Input
5 5 35552 31154 33222 21134 12314
 

Sample Output
5 2 2 0 0 1 1 2 1 4 4
Hint
35552 35000 00000 00000 00000 00000 31154 31552 05552 00002 00002 00000 33222 33154 01154 01104 00004 00000 21134 21134 21134 21134 20034 20030 12314 12314 12314 12314 12314 12312 The total point is 6+12+12+12+6=48.
 

思路:总体是用BFS搞的,消除格子的时候就用DFS。对每一个状态都求一个评估值val,用优先队列来维护,每次使评估值最大的元素出队,并且更新答案。题目不要求最优解,处理25次左右就可以满足题意了。

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

struct S{
char mp[20][21];
int step,ans,x[50],y[50],val;
int num[20][20];

bool operator<(const S &p) const
{
    return val<p.val;
}

}t,ans,tt;

int n,m,nxt[4][2]={{1,0},{0,1},{-1,0},{0,-1}},cnt;
char temp[20][21];
bool vis[20][20];

void dfs(int x,int y,char c)
{
    int i,j;

    for(i=0;i<4;i++)
    {
        x+=nxt[i][0];
        y+=nxt[i][1];

        if(x>=0 && x<n && y>=0 && y<m && !vis[x][y] && temp[x][y]==c)
        {
            vis[x][y]=1;

            cnt++;

            dfs(x,y,c);
        }

        x-=nxt[i][0];
        y-=nxt[i][1];
    }
}

void tran(int x,int y,char num,char (*d)[21])
{
    for(int i=0;i<4;i++)
    {
        x+=nxt[i][0];
        y+=nxt[i][1];

        if(x>=0 && x<n && y>=0 && y<m && d[x][y]==num)
        {
            d[x][y]='0';

            tran(x,y,num,d);
        }

        x-=nxt[i][0];
        y-=nxt[i][1];
    }
}

void move(char (*d)[21])
{
    int i,j,k;

    for(i=n-1;i>=0;i--)//向下移动
    {
        for(j=0;j<m;j++)
        {
            if(d[i][j]=='0')
            {
                for(k=i-1;k>=0;k--)
                {
                    if(d[k][j]>'0')
                    {
                        d[i][j]=d[k][j];
                        d[k][j]='0';

                        break;
                    }
                }
            }
        }
    }

    int t=m-1;
    while(t--)//向左移动,注意连续两列都为空的情况
    {
        for(j=0;j<m-1;j++)
        {
            for(i=0;i<n;i++) if(d[i][j]>'0') break;

            if(i==n)
            {
                for(i=0;i<n;i++)
                {
                    d[i][j]=d[i][j+1];

                    d[i][j+1]='0';
                }
            }
        }
    }
}

void eval(S &node)//评估
{
    int i,j;

    for(i=0;i<n;i++) for(j=0;j<m;j++) vis[i][j]=0,temp[i][j]=node.mp[i][j];

    node.val=node.ans;

    for(i=0;i<n;i++) for(j=0;j<m;j++)
    {
        node.num[i][j]=0;

        if(temp[i][j]>'0' && !vis[i][j])
        {
            vis[i][j]=1;

            cnt=1;

            dfs(i,j,temp[i][j]);

            if(cnt>1)
            {
                node.num[i][j]=cnt;

                node.val+=cnt*(cnt-1);
            }
        }
    }
}

int main()
{
    int i,j,p,q,tot;

    while(~scanf("%d%d",&n,&m))
    {
        for(i=0;i<n;i++) scanf("%s",t.mp[i]);

        t.step=0;
        t.ans=0;
        t.val=0;

        ans.ans=0;

        priority_queue<S>que;

        eval(t);

        que.push(t);

        tot=0;

        while(!que.empty())
        {
            t=que.top();

            if(t.ans>ans.ans) ans=t;//更新答案

            tot++;

            if(tot>24) break;//循环25次就退出

            que.pop();

            for(i=0;i<n;i++) for(j=0;j<m;j++)
            {
                if(t.num[i][j])
                {
                    tt=t;
                    
                    tran(i,j,t.mp[i][j],t.mp);//清除格子

                    t.mp[i][j]='0';

                    move(t.mp);//移动格子

                    t.x[t.step]=i;
                    t.y[t.step]=j;
                    t.step++;
                    t.ans+=t.num[i][j]*(t.num[i][j]-1);

                    eval(t);//重新评估

                    que.push(t);

                    t=tt;
                }
            }
        }

        printf("%d\n",ans.step);

        for(i=0;i<ans.step;i++) printf("%d %d\n",ans.x[i],ans.y[i]);
    }
}

HDU-2259-Continuous Same Game (2)(BFS+DFS+模拟)