hdu 4090 GemAnd Prince
题目大意:
别人说是消消看,至于你玩没玩过。反正我是没玩过的。
就是选择一个钻石,可以消除与它相连的所有钻石。并获得 消除数量*消除数量 的分
思路:
直接暴搜,然后用一个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的更多相关文章
- hdu 4090
GemAnd Prince Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- HDU 4685 Prince and Princess 二分图匹配+tarjan
Prince and Princess 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 Description There are n pri ...
- HDU 4685 Prince and Princess(二分图+强连通分量)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...
- Prince and Princess HDU - 4685(匹配 + 强连通)
Prince and Princess Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Othe ...
- 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 ...
- H - Prince and Princess - HDU 4685(二分匹配+强连通分量)
题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚. 分析:先求出来他们的最大匹配,因为给的数据未必是完备 ...
- hdu 4685 Prince and Princess(匈牙利算法 连通分量)
看了别人的题解.须要用到匈牙利算法的强连通算法 #include<cstdio> #include<algorithm> #include<vector> #pra ...
- HDU 4685 Prince and Princess(二分匹配+强联通分量)
题意:婚配问题,但是题目并不要求输出最大匹配值,而是让我们输出,一个王子可以与哪些王妃婚配而不影响最大匹配值. 解决办法:先求一次最大匹配,如果有两个已经匹配的王妃,喜欢她们两个的有两个或者以上相同的 ...
- HDU 4685 Prince and Princess
强连通分量,看大神的题解才会写的.... http://www.cnblogs.com/kuangbin/p/3261157.html 数据量有点大,第一次Submit 2995ms过的,时限3000 ...
随机推荐
- 一致性算法--Paxos
分布式一致性算法--Paxos Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法.Paxos算法解决的问题是一个分布式系统如何就某个值(决议) ...
- ASP.NET MVC 5 学习教程:Details 和 Delete 方法详解
原文 ASP.NET MVC 5 学习教程:Details 和 Delete 方法详解 在教程的这一部分,我们将研究一下自动生成的 Details 和Delete 方法. Details 方法 打开M ...
- nginx区分手机与电脑浏览器并进入相应站点
本文要讲的的是如何使用nginx区分pc和手机访问不同的网站,是物理上完全隔离的两套网站(一套移动端.一套pc端),这样带来的好处pc端和移动端 的内容可以不一样,移动版网站不需要包含特别多的内容,只 ...
- UVA 531 - Compromise(dp + LCS打印路径)
Compromise In a few months the European Currency Union will become a reality. However, to join th ...
- HapiJS开发手冊
HapiJS开发手冊 作者:chszs.转载需注明.博客主页:http://blog.csdn.net/chszs 一.HapiJS介绍 HapiJS是一个开源的.基于Node.js的应用框架,它适用 ...
- HDU 3336 Count the string KMP
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3336 如果你是ACMer,那么请点击看下 题意:求每一个的前缀在母串中出现次数的总和. AC代码: # ...
- UVa 725暴力求解
A - Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Su Description Writ ...
- arm: 使用结构体操作寄存器
使用结构体操作寄存器: //寄存器赋值和取值的时候,要注意寄存器的长度,有的寄存器的值只有8位. //还要注意,使用volatile修饰寄存器变量.volatile 参考http://www.cnbl ...
- 自定义Log4cpp的日志输出格式
// 1. 实例化一个PatternLayout对象 log4cpp::PatternLayout* pLayout = new log4cpp::PatternLayout(); // 2. 实例化 ...
- BZOJ 1854: [Scoi2010]游戏( 二分图最大匹配 )
匈牙利算法..从1~10000依次找增广路, 找不到就停止, 输出答案. --------------------------------------------------------------- ...