POJ
来源:互联网 发布:mac 中文字幕乱码 编辑:程序博客网 时间:2024/05/21 01:44
题目大意:
多组测试实例(50),每组测试给你一个图(50*50),然后给你一个S点和若干个A点(100)。一个小人从点S开始,他在S点或者A点可以分别成多个小人。现在他要访问到每个点,让你求出他要走的最少的距离。
注意: 只有当borg在S点或者找到一个alien之后,它们可以继续以分成若干的小队伍。
思路:
只有在S和A可以分裂,这表示了什么?这表示这个图(无向),每个顶点(A或S)可以有多个边!然后想到最小生成树,但是每一对点之间的距离怎么计算呢,我觉得就是用广搜确定出来的,就是他们之间的距离(因为有距离)。
这个复杂度可能不小,得算一下:
100个点,两个之间一搜索,100*101/2=5050个搜索,每个图50*50=2500个点(如果全部都要访问一次的话),每组测试实例确定距离需要5000*2500=12,500,000。50组:50* 12,500,000=625,000,000。当然这个是最坏的情况。
然后问题就简化成一个图,求它的最小生成树。我感觉这个图边应该很多,如果用prim枚举点的话,应该是比较划算的。但是仔细一想,因为求最小生成树的过程和n次广搜的过程是并列的,所以慢一点也没关系,反正肯定比n次广搜快,我就写的kruckal。
这次要是还不ac我就要吐血了~
代码:
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#define maxxy 55#define maxn 105#define inf 0x3f3f3f3fusing namespace std;int n;int map[maxxy][maxxy]={0};int dis[maxn][maxn]={0};int num[maxxy][maxxy];struct point{ int x; int y;}a[maxn];struct edge{ int s;int e;int v;}b[maxn*maxn]; int x,y;int move[4][2]={{1,0},{-1,0},{0,1},{0,-1}};int boss[maxn]={0};int find(int x){ return boss[x]==x?x:boss[x]=find(boss[x]);}void match(int a,int b){ int fa=find(a); int fb=find(b); boss[fa]=fb; return;}void ceshi1(){ for(int i=1;i<=y;i++) { for(int j=1;j<=x;j++) { cout<<map[i][j]; } cout<<endl; }}void ceshi2(){ for(int i=1;i<=n;i++) { cout<<a[i].x<<" "<<a[i].y<<endl; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cout<<dis[i][j]<<" "; } cout<<endl; }}bool my_cmp(edge a,edge b){ return a.v<b.v;}void bfs(int k)//从k号点开始广搜 { bool vis[maxxy][maxxy]={0}; int v[maxxy][maxxy]={0}; queue<point>q; q.push(a[k]); vis[a[k].x][a[k].y]=1; v[a[k].x][a[k].y]=0; while(!q.empty()) { for(int i=0;i<4;i++) { point l; l.x=q.front().x+move[i][1]; l.y=q.front().y+move[i][0]; if(l.x>x||l.x<1||l.y>y||l.y<1)continue; if(vis[l.x][l.y])continue; if(map[l.x][l.y]==1)continue; v[l.x][l.y]=v[q.front().x][q.front().y]+1; q.push(l); vis[l.x][l.y]=1; if(map[l.x][l.y]==2) { dis[k][num[l.x][l.y]]=v[l.x][l.y]; } } q.pop(); }}int my_kruskal(){ for(int i=0;i<=n;i++) { boss[i]=i; } int s=0; int num=0; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { num++; b[num].s=i; b[num].e=j; b[num].v=dis[i][j]; } } sort(b+1,b+num+1,my_cmp); for(int i=1;i<=num;i++) { //cout<<find(b[i].s)<<" "<<find(b[i].e)<<endl; if(find(b[i].s)==find(b[i].e))continue; match(b[i].s,b[i].e); s+=b[i].v; } return s;}int main(){ int test; scanf("%d",&test); while(test--) { char c; scanf("%d %d",&x,&y); while(c!='\n') { scanf("%c",&c); } n=1; memset(map,0,sizeof(map)); memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=y;i++) { for(int j=0;j<=x;j++)//墙1,外星人2,空位0 { scanf("%c",&c); if(c=='#')map[j+1][i]=1; if(c=='A') { map[j+1][i]=2; n++; a[n].x=j+1;a[n].y=i; num[j+1][i]=n; } if(c=='S') { map[j+1][i]=2; a[1].x=j+1;a[1].y=i; num[j+1][i]=1; } } } //ceshi1(); for(int i=1;i<=n;i++) { bfs(i); } //ceshi2(); cout<<my_kruskal()<<endl; }}
另外附上以前寒假时候写的错的代码,也许有一天我真的会去查查以前是怎么错的吧,主要是实在不舍得删啊。这一段你们就不要看了。。。。
#include<iostream>#include<stdio.h>#include<queue>#include<math.h>#include<string.h>#define xy_max 65#define N 120#define inf 0x3f3f3f3fusing namespace std;struct point{ int x; int y;}poi[N]={0};int x,y; int n;//点的个数 char map[xy_max][xy_max];int dis[N][N]={0};//1号点为Sint deep[xy_max][xy_max]={0};//点ij到原点的距离 bool vis[xy_max][xy_max]={0};int mincost[N]={0};bool inside[N]={0};void input(){ memset(map,0,sizeof(map)); n=2; cin>>x>>y; char c; scanf("%c",&c);//注意要读取数字行的换行符 for(int i=1;i<=y;i++) { for(int j=1;j<=x+1;j++) { scanf("%c",&map[i][j]); if(map[i][j]=='S') { poi[1].x=j; poi[1].y=i; } if(map[i][j]=='A') { poi[n].x=j; poi[n].y=i; n++; } } }}void bfs(int v)//对v号点进行dfs { point k=poi[v]; int fx[4]={-1,0,1,0}; int fy[4]={0,1,0,-1}; memset(deep,0,sizeof(deep)); memset(vis,0,sizeof(vis)); queue<int>qx; queue<int>qy; qx.push(k.x); qy.push(k.y); deep[k.y][k.x]=0; vis[k.y][k.x]=1; while(1) { if(qx.empty()&&qy.empty())break; for(int i=0;i<4;i++)//向四个方向扩展 { if(qy.front()+fy[i]<=0||qy.front()+fy[i]>y||qx.front()+fx[i]<=0||qx.front()+fx[i]>x)continue; if(vis[qy.front()+fy[i]][qx.front()+fx[i]])continue; if(map[qy.front()+fy[i]][qx.front()+fx[i]]=='#')continue; deep[qy.front()+fy[i]][qx.front()+fx[i]]=deep[qy.front()][qx.front()]+1; vis[qy.front()+fy[i]][qx.front()+fx[i]]=1; qx.push(qx.front()+fx[i]); qy.push(qy.front()+fy[i]); } qx.pop(); qy.pop(); } for(int i=1;i<n;i++) { dis[v][i]=deep[poi[i].y][poi[i].x]; }} void ceshi1(){ for(int i=1;i<n;i++) { cout<<poi[i].y<<poi[i].x; cout<<endl; }} void ceshi2(){ for(int i=1;i<n;i++) { for(int j=1;j<n;j++)cout<<dis[i][j]; cout<<endl; }}int numout(){ int s=0; for(int i=1;i<n;i++) { if(inside[i]==0)s++; } return s;}int my_prim(){ int v=1; int s=0; memset(inside,0,sizeof(inside)); inside[1]=1; for(int i=1;i<n;i++) { mincost[i]=dis[1][i]; } while(1) { if(numout()==0)break; int min=inf; for(int i=1;i<n;i++)//找到即将入图的点号v { if(inside[i]==1)continue; if(min>mincost[i]) { min=mincost[i]; v=i; } } s=s+min; inside[v]=1; for(int i=1;i<n;i++) { if(inside[i]==1)continue; if(mincost[i]>dis[v][i]) { mincost[i]=dis[v][i]; } } } return s;}int main(){ int cs=0; cin>>cs; while(cs--) { input(); for(int i=1;i<n;i++)bfs(i); //ceshi2(); //ceshi1(); cout<<my_prim()<<endl; }}/*86 5##### #A#A### # A##S ####### 7 7##### #AAA#### A## S #### ##AAA######## 6 5##### #A#A### # A##S ####### 7 7##### # #### ## S #### ## ######## */
后记:
出问题可以先偷偷看下discuss。这道题输入数据中输入地图大小的两个数所在的那一行,两个数后面可能会有若干空格。
0 0
- POJ
- poj
- POJ
- POJ
- poj
- poj
- POJ
- POJ
- poj
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- 互斥锁和条件变量(1)
- (转)今天的人工智能比肩工业革命毫不夸张
- 迪杰斯特拉算法(可打印最短路径)
- strchr函数的使用
- 枚举转化为JSON字符串
- POJ
- 查看安装的centos的版本信息
- HDU 1484 Basic wall maze
- 如何优化js代码
- 前端框架Vue(9)——百度地图使用
- iOS之UITableView(二)系统自带的刷新UIrefreshControl
- BZOJ4832 [Lydsy2017年4月月赛]抵制克苏恩
- HTML标签锚标签
- AngularJs—控制器 <controller>