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;
}
本文探讨了一种在特定范围内的宝石消除游戏中的优化搜索算法。通过剪枝技巧,作者提高了算法效率,解决了得分最大化的问题。算法在计算剩余宝石得分的基础上,进一步统计不同颜色的宝石数量,从而实现高效计算。此方法适用于类似问题的解决。
381

被折叠的 条评论
为什么被折叠?



