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