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

本文探讨了一种在面对复杂问题时改进的贪心策略与深度优先搜索方法的应用。通过实例分析,展示如何通过算法优化提升解决方案效率。详细介绍了算法设计、实现步骤及性能评估过程,旨在为解决实际问题提供新的思考角度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值