题目大意:

别人说是消消看,至于你玩没玩过。反正我是没玩过的。

就是选择一个钻石,可以消除与它相连的所有钻石。并获得 消除数量*消除数量  的分

思路:

直接暴搜,然后用一个cnt数组表示每一种钻石剩余的数量,进行剪枝。

被坑了两天。 开始用BFS 搜,用DFS进行标记。超内存。

后来改成了  DFS + DFS 发现有些细节不好处理。

最后换成了DFS搜  BFS标记消除。

#include <iostream>
#include <cstdio>
#include <algorithm> using namespace std;
int dx[] = {0,0,1,-1,1,1,-1,-1};
int dy[] = {1,-1,0,0,1,-1,-1,1}; int n,m,k;
int map[9][9]; int save[9][9][70];
bool vis[9][9][70];
int cnt[7];
int ans; struct node
{
int posx,posy;
}Q[1000];
bool ok(int x,int y)
{
if(x>=1 && x<=n && y>=1 && y<=m)return true;
return false;
}
void mtos(int dep)//存地图
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
save[i][j][dep]=map[i][j];
}
void stom(int dep)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
map[i][j]=save[i][j][dep];
} void reset(int top)//重新摆放
{
for(int i=0;i<top;i++)//与后面的BFS 对应 消除。
map[Q[i].posx][Q[i].posy]=0; int tmp[9][9]; int ii,jj;
for(int j=1;j<=m;j++)
{
ii=n;
for(int i=n;i>=1;i--)
{
if(map[i][j]!=0)
{
jj=j;
tmp[ii--][jj]=map[i][j];
}
}
while(ii>=1)
{
tmp[ii][j]=0;
ii--;
}
} int move[9],ccnt=0;
memset(move,0,sizeof(move)); for(int j=1;j<=m;j++)
{
if(tmp[n][j]==0)
{
move[j]=0;
ccnt++;
continue;
}
move[j]=ccnt;
}
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
{
tmp[i][j-move[j]]=tmp[i][j];
if(move[j])tmp[i][j]=0;
}
} for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
map[i][j]=tmp[i][j];
}
inline int h()//估价函数 剪枝
{
int sum=0; for(int i=1;i<=k;i++)
if(cnt[i]>=3)sum+=(cnt[i]*cnt[i]); return sum;
} int mark(int x,int y,int val,int dep)//进行标记
{
int head=0,tail=0;
node w,e; Q[tail].posx=x;
Q[tail++].posy=y;
vis[x][y][dep]=true;
while(head<tail)
{
w=Q[head];
head++;
for(int i=0;i<8;i++)
{
e=w;
int xx=e.posx+dx[i];
int yy=e.posy+dy[i]; if(ok(xx,yy) && !vis[xx][yy][dep] && map[xx][yy]==val)
{
vis[xx][yy][dep]=true;
e.posx=xx;
e.posy=yy;
Q[tail++]=e;
}
}
}
return tail;
} void dfs(int tans,int dep)
{
ans=max(ans,tans);
if(h()+tans<=ans)return; for(int i=1;i<=n;i++)//这里不可少 没进入一次新的DFS 都要重置
for(int j=1;j<=m;j++)
vis[i][j][dep]=false; for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(map[i][j]!=0 && !vis[i][j][dep])
{
int tscore=mark(i,j,map[i][j],dep); if(tscore>=3)
{
mtos(dep);
int vv=map[i][j];//被这里坑了好久 RESET之后地图就会变了。无力吐槽自己
cnt[vv]-=tscore;
reset(tscore);
dfs(tans+tscore*tscore,dep+1);
cnt[vv]+=tscore;
stom(dep);
}
}
}
}
} int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
cnt[map[i][j]]++;
}
ans=0;
memset(vis,false,sizeof(vis)); dfs(0,1);
printf("%d\n",ans);
}
return 0;
} /*
8 8 6
1 1 1 2 2 2 3 3
4 4 1 1 4 4 4 4
5 5 5 6 6 6 6 1
2 2 2 2 4 4 4 3
1 4 5 6 3 3 2 1
4 4 4 5 5 5 5 6
5 5 5 5 5 3 3 3
5 5 2 2 2 1 3 1
*/

这里在给出DFS + DFS 的 AC代码。 效率没有上一个快,只是为了检验自己之前的错误。

#include <iostream>
#include <cstdio>
#include <algorithm> using namespace std;
int dx[] = {0,0,1,-1,1,1,-1,-1};
int dy[] = {1,-1,0,0,1,-1,-1,1};
int n,m,k;
int map[9][9]; int save[9][9][70];
bool vis[9][9][70];
int cnt[7];
int tscore;
int ans; void debugcnt()
{
for(int i=1;i<=k;i++)
printf("%d ",cnt[i]); puts("");
system("pause");
// getchar();
}
bool ok(int x,int y)
{
if(x>=1 && x<=n && y>=1 && y<=m)return true;
return false;
}
void debug()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("%d",map[i][j]);
}
puts("");
}
puts("");
//getchar();
}
void mtos(int dep)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
save[i][j][dep]=map[i][j];
}
}
void stom(int dep)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
map[i][j]=save[i][j][dep];
}
}
void reset()
{
int tmp[9][9]; int ii,jj;
for(int j=1;j<=m;j++)
{
ii=n;
for(int i=n;i>=1;i--)
{
if(map[i][j]!=0)
{
jj=j;
tmp[ii--][jj]=map[i][j];
}
}
while(ii>=1)
{
tmp[ii][j]=0;
ii--;
}
} int move[9],ccnt=0;
memset(move,0,sizeof(move)); for(int j=1;j<=m;j++)
{
if(tmp[n][j]==0)
{
move[j]=0;
ccnt++;
continue;
}
move[j]=ccnt;
}
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
{
tmp[i][j-move[j]]=tmp[i][j];
if(move[j])tmp[i][j]=0;
}
} for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
map[i][j]=tmp[i][j];
}
int h()
{
int sum=0;
for(int i=1;i<=k;i++)
if(cnt[i]>=3)sum+=cnt[i]*cnt[i];
return sum;
} void mark(int x,int y,int val,int dep)
{
for(int i=0;i<8;i++)
{
int xx=dx[i]+x;
int yy=dy[i]+y;
if(ok(xx,yy) && !vis[xx][yy][dep] && map[xx][yy]==val)
{
vis[xx][yy][dep]=true;
map[xx][yy]=0;
tscore++;
mark(xx,yy,val,dep);
}
}
} void dfs(int tans,int dep)
{
if(tans+h()<=ans){return;}
ans=max(ans,tans); for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
vis[i][j][dep]=false; for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(map[i][j]!=0 && !vis[i][j][dep])
{
mtos(dep);
int tt;
tscore=0;
int vv=map[i][j]; mark(i,j,map[i][j],dep);
tt=tscore;
if(tt<3){stom(dep);continue;}
cnt[vv]-=tt;
reset();
dfs(tans+tt*tt,dep+1);
cnt[vv]+=tt;
stom(dep);
}
}
}
} int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
cnt[map[i][j]]++;
}
ans=0;
dfs(0,1); printf("%d\n",ans);
}
return 0;
}

再上一份自己之前超内存的BFS 的代码。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring> using namespace std;
int dx[] = {0,0,-1,1,1,1,-1,-1};
int dy[] = {1,-1,0,0,1,-1,1,-1};
int n,m,k;
struct node
{
short map[9][9];
int score;
}; bool vis[9][9];
bool v[9][9];
bool ok(int x,int y)
{
if(x<=n && x>=1 && y>=1 && y<=m)return true;
return false;
}
int tscore; void dfs(int x,int y,node &t,int val)
{
for(int i=0;i<8;i++)
{
int xx=dx[i]+x;
int yy=dy[i]+y;
if( ok(xx,yy) && !vis[xx][yy] && t.map[xx][yy]==val)
{
vis[xx][yy]=true;
t.map[xx][yy]=0;
tscore++;
v[xx][yy]=true;
dfs(xx,yy,t,val);
}
}
}
int h(node t)
{
int tcnt[7]; for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(t.map[i][j]!=0)
{
tcnt[t.map[i][j]]++;
}
}
}
int sum=0;
for(int i=1;i<=k;i++)
if(tcnt[i]>=3)sum+=tcnt[i]*tcnt[i]; return sum;
}
node reset(node t)
{
node tmp=t;
int ii,jj;
for(int j=1;j<=m;j++)
{
ii=n;
for(int i=n;i>=1;i--)
{
if(t.map[i][j]!=0)
{
jj=j;
tmp.map[ii--][jj]=t.map[i][j];
}
}
while(ii>=1)
{
tmp.map[ii][j]=0;
ii--;
}
}
//debug(tmp); int move[9],ccnt=0;
memset(move,0,sizeof(move)); for(int j=1;j<=m;j++)
{
if(tmp.map[n][j]==0)
{
move[j]=0;
ccnt++;
continue;
}
move[j]=ccnt;
}
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
{
tmp.map[i][j-move[j]]=tmp.map[i][j];
if(move[j])tmp.map[i][j]=0;
}
}
return tmp;
}
int ans;
void bfs(node t)
{
queue<node>Q; node w,e;
Q.push(t); while(!Q.empty())
{
w=Q.front();
Q.pop(); if(w.score>ans)
{
ans=w.score;
}
memset(v,false,sizeof(v)); for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(v[i][j])continue;
if(w.map[i][j]!=0)
{
e=w;
tscore=0;
memset(vis,false,sizeof(vis));
dfs(i,j,e,e.map[i][j]); if(tscore>=3)
{
e=reset(e);
e.score+=(tscore*tscore);
if(e.score+h(e)<=ans)continue;
Q.push(e);
}
}
}
}
}
}
int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
node t;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&t.map[i][j]);
} t.score=0;
ans=0;
bfs(t);
printf("%d\n",ans);
}
return 0;
}

hdu 4090 GemAnd Prince的更多相关文章

  1. hdu 4090

    GemAnd Prince Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  2. HDU 4685 Prince and Princess 二分图匹配+tarjan

    Prince and Princess 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 Description There are n pri ...

  3. HDU 4685 Prince and Princess(二分图+强连通分量)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...

  4. Prince and Princess HDU - 4685(匹配 + 强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  5. HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  6. H - Prince and Princess - HDU 4685(二分匹配+强连通分量)

    题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚. 分析:先求出来他们的最大匹配,因为给的数据未必是完备 ...

  7. hdu 4685 Prince and Princess(匈牙利算法 连通分量)

    看了别人的题解.须要用到匈牙利算法的强连通算法 #include<cstdio> #include<algorithm> #include<vector> #pra ...

  8. HDU 4685 Prince and Princess(二分匹配+强联通分量)

    题意:婚配问题,但是题目并不要求输出最大匹配值,而是让我们输出,一个王子可以与哪些王妃婚配而不影响最大匹配值. 解决办法:先求一次最大匹配,如果有两个已经匹配的王妃,喜欢她们两个的有两个或者以上相同的 ...

  9. HDU 4685 Prince and Princess

    强连通分量,看大神的题解才会写的.... http://www.cnblogs.com/kuangbin/p/3261157.html 数据量有点大,第一次Submit 2995ms过的,时限3000 ...

随机推荐

  1. Python 2.7 学习笔记 列表的使用

    同其它编程语言一样,python也提供了丰富的数据结构,以方便数据的处理.本文介绍两种最基本的数据集合,列表和元组的使用. 一.列表使用介绍 可以理解为一个有序的序列.其使用方式举例如下: list= ...

  2. 基于visual Studio2013解决算法导论之054图的邻接矩阵表示

     题目 图的邻接矩阵表示 解决代码及点评 // 图的邻接矩阵表示.cpp : 定义控制台应用程序的入口点. // #include <iostream> #include <l ...

  3. [蘑菇街] 搜索、算法团队招募牛人啦-年底了走过路过不要错过 - V2EX

    [蘑菇街] 搜索.算法团队招募牛人啦-年底了走过路过不要错过 - V2EX [蘑菇街] 搜索.算法团队招募牛人啦-年底了走过路过不要错过

  4. Global文件(修正篇)

    什么是Global文件 Global.asax文件俗称为一个类,继承于Httpapplication类.位于应用程序根目录下.也可称为应用程序文件. 概述: Global文件是可选的,一般在创建应用程 ...

  5. 浅析Java中的反射机制原理

    反射反射,程序员的快乐! Java中反射机制使用的还是比较广泛的,系统的灵活性.可扩展性大都都是通过反射等方式来加载外部插件,使得系统与插件解耦的同时,增加了功能.但是很多人都只是会用,却是不知道它的 ...

  6. 云计算与虚拟化以及IaaS, PaaS和SaaS

    概述: 包括:服务器虚拟化.桌面虚拟化.应用虚拟化: 云计算只是用到了虚拟化的技术: soa dubbo结构,阿里巴巴的开源架构: netstat -ntlp; 云服务”现在已经快成了一个家喻户晓的词 ...

  7. log4cpp的初步使用

    (1)下载log4cpp的工程,编译生成lib文件和dll库 下载路径为:http://sourceforge.net/projects/log4cpp/files/latest/download 如 ...

  8. 在C++中使用C#编写的类2

    在那篇<在C#中使用C++编写的类>中我介绍了如何在C#中使用C++编写的类.可是由于C#在用户界面设计.数据库存储和XML文件读取等方面的优势,有时候也会出现要在C++中使用C#编写的类 ...

  9. TFT ST7735的Netduino驱动

    好久没写关于netduino的文章了,工作忙是一方面,主要原因还是因为没解决TFT显示的问题,功夫不负有心人,在经过多轮研究后,总算在今天2013年12月15日的晚上9点解决了. 下面先介绍一下我所用 ...

  10. Python 第六篇(上):面向对象编程初级篇

    面向:过程.函数.对象: 面向过程:根据业务逻辑从上到下写垒代码! 面向过程的编程弊:每次调用的时候都的重写,代码特别长,代码重用性没有,每次增加新功能所有的代码都的修改!那有什么办法解决上面出现的弊 ...