hdu 4090 GemAnd Prince DFS+启发剪枝

        n*m(最大8*8)的范围内有不超过6中颜色的宝石,每次可以选择一颗宝石,把与它连通(八方向扩展)的所有宝石消去,一次消去的得分是消除宝石数量的平方。并且消除之后,空隙上方的宝石会下落,底层左侧为空的话,便整体左移。给一个初始状态,问最大的得分。看数据规模明显就是让写搜索的,但肯定不会让裸的爆搜直接过掉- -,关键就是怎么剪枝了。我的写法是在搜索的过程中,把当前能得到的最大的分数记录一下,每到一个状态,计算一下当前状态最大还可能得多少分,如果当前的分数加上这个分数还达不到最大的分数,显然就不用继续往下走了。我已开始写算分的函数时,直接返回了剩下宝石数的平方- 事实证明我太天真了果断TLE= =,后来改成统计一下剩下的每种颜色的宝石各有多少个,大于等于3的求一个平方和,就过掉了...

       

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <memory.h>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
const int fx[8]={-1,-1,0,1,1,1,0,-1};
const int fy[8]={0,1,1,1,0,-1,-1,-1};

int site[9][9];
bool ck[9][9];
int n,m,k;
int mid;
int out;
void debug()
{
    for (int i=1; i<=n; i++)
    {
        for (int j=1; j<=m; j++)
        cout<<site[i][j]<<" ";
        cout<<endl;
    }
}
bool check(int x,int y)
{
    if (x>0 && x<=n && y>0 && y<=m) return true;
    return false;
}
int con(int x,int y,int c,bool vs[][9])
{
   site[x][y]=0;
   vs[x][y]=true;
   int tx,ty;
   int res=1;
   for (int j=0; j<8; j++)
   {
       tx=x+fx[j];
       ty=y+fy[j];
       if (check(tx,ty) && site[tx][ty]==c)
       res+=con(tx,ty,c,vs);
   }
   return res;
}
void work()
{
    for (int i=1; i<=n; i++)
     for (int j=1; j<=m; j++)
     if (site[i][j]==0)
     {
         for (int k=i; k>=1; k--)
         if (k>1) site[k][j]=site[k-1][j];
         else site[k][j]=0;
     }
    for (int j=m; j>=1; j--)
    if (site[n][j]==0)
    {
        for (int k=j; k<=m; k++)
        for (int i=1; i<=n; i++)
        if (k<m) site[i][k]=site[i][k+1];
        else site[i][k]=0;
    }
}
int maxsc()
{
    int ct[10];
    memset(ct,0,sizeof ct);
    for (int i=1; i<=n; i++)
    for (int j=1; j<=m; j++)
    if (site[i][j]>0 && site[i][j]<=6) ct[site[i][j]]++;
    int res=0;
    for (int i=1; i<=6; i++)
    if (ct[i]>=3) res+=ct[i]*ct[i];
    return res;
}
void dfs(int score,int res)
{
    out=max(out,score);
//    debug(); cout<<endl;
//    cout<<out<<" "<<score<<" "<<maxsc()<<endl;
    if (score+res*res<=out) return;
    int tmp[9][9];
    bool vs[9][9];
    memset(vs,false,sizeof vs);
    int s;
    memcpy(tmp,site,sizeof tmp);
    bool flag=false;
    bool ft=false;
    for (int i=1; i<=n; i++)
     for (int j=1; j<=m; j++)
     {
         if (site[i][j] && !vs[i][j])
         {
             s=con(i,j,site[i][j],vs);
             if (s>=3 && score+s*s+maxsc()>out)
             {
                work();
//                debug();cout<<endl;
                dfs(score+s*s,res-s);
             }
             memcpy(site,tmp,sizeof tmp);

         }
     }
}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        memset(site,0,sizeof site);
        for (int i=1; i<=n; i++)
         for (int j=1; j<=m; j++)
         {
             scanf("%d",&site[i][j]);
         }
         out=0;
        dfs(0,n*m);
        printf("%d\n",out);
    }
    return 0;
}

你可能感兴趣的:(hdu 4090 GemAnd Prince DFS+启发剪枝)