您的位置:首页 > 其它

POJ 1789--Truck History(最小生成树)

2014-08-04 11:55 495 查看
本题要求最小生成树,因为已经是最大团,建议采用prim算法。

Prim算法实质为贪心思想,每次我们只选择一个到已加入生成树集合的点距离最近的点即可,且每加入一个新点都要更新其他点的最短距离。

最朴素的做法,设置一个是否在生成树集合的bool数组以及一个标志点到生成树的最小距离的数组,每次加入新点,更新最小距离时,且可以直接找出下一个加入的点。

另一种做法:因为本题距离只在1到7之间,想用类似hash的思想,设置7个队列,把最小距离为i的点直接放进队列q[i]中,这样每次从1到7遍历队列,遇到第一个没在生成树的点就说明此点位下一个加入生成树中的点,但是因为当最小距离更新时,我们不能删除这个点在较大距离的队列中的元素,所以有很多冗余,效果不理想。

Prim:

#include<cstdio>
#include<cstring>
#define maxN 2001
#define maxL 8
#define INF 0X7F7F7F7F

int truckNum;
char truckCode[maxN][maxL];

char typeDis(int x,int y)
{
char dis = 0;
for(int i = 0;i < maxL-1;i++)
{
if(truckCode[x][i] != truckCode[y][i])
dis++;
}
return dis;
}

int search_Prim()
{
int i,j;
char truckDis[maxN];     //保存卡车到已加入生成树中的卡车最小距离
char IsInTree[maxN];
int minTrucknextTruck;
int tmpDis,sumDis,minDis;
sumDis = 0;
memset(IsInTree,0,sizeof(IsInTree));
memset(truckDis,0X7F,sizeof(truckDis));
nextTruck = 0;
for(i = 1;i < truckNum;i++)
{
minTruck = nextTruck;
IsInTree[minTruck] = true;
minDis = INF;
for(j = 1;j < truckNum;j++)
{
if(!IsInTree[j])
{
tmpDis = typeDis(minTruck,j);
if(truckDis[j] > tmpDis)      //更新最小距离
truckDis[j] = tmpDis;
if(truckDis[j] < minDis)      //从不在生成树中的点选择下一个加入树中的点
{
minDis = truckDis[j];
nextTruck = j;
}
}
}
sumDis += minDis;
}
printf("The highest possible quality is 1/%d.\n",sumDis);
return 0;
}

int main()
{
while(scanf("%d",&truckNum)&&truckNum)
{
getchar();
for(int i = 0;i < truckNum;i++)
gets(truckCode[i]);
search_Prim();
}
return 0;
}


Prim&Queue:

#include<cstdio>
#include<cstring>
#define maxN 2001
#define maxL 8
#define INF 0X7F7F7F7F
#define qSize  2000

int truckNum;
char truckCode[maxN][maxL];

class queue_self
{
short q[qSize+1];
int qHead;
int qTail;
public:
queue_self():qHead(0),qTail(0){}
void enQueue(int x)
{
q[qTail] = x;
if(qTail == qSize)
qTail = 0;
else qTail++;
}
short deQueue()
{
short x = q[qHead];
if(qHead == qTail)
qHead = 0;
else qHead++;
return x;
}
bool empty()
{
if(qHead == qTail)
return true;
else return false;
}
};

char typeDis(int x,int y)
{
char dis = 0;
for(int i = 0;i < maxL-1;i++)
{
if(truckCode[x][i] != truckCode[y][i])
dis++;
}
return dis;
}

int search_Prim()
{
int i,j;
char truckDis[maxN];
char IsInTree[maxN];
int minTruck;
int minDis,tmpDis,sumDis;
char IsFindMin;
queue_self q[maxL];
sumDis = 0;
memset(IsInTree,0,sizeof(IsInTree));
memset(truckDis,0X7F,sizeof(truckDis));
truckDis[0] = 1;
q[1].enQueue(0);
for(i = 0;i < truckNum;i++)
{
IsFindMin = false;
for(minDis = 1;minDis < maxL;minDis++)
{
while(!q[minDis].empty())
{
j = q[minDis].deQueue();
if(!IsInTree[j])
{
minTruck = j;
IsFindMin = true;
break;
}
}
if(IsFindMin)
break;
}
sumDis += minDis;
IsInTree[minTruck] = true;
for(j = 1;j < truckNum;j++)
{
if(!IsInTree[j])
{
tmpDis = typeDis(minTruck,j);
if(truckDis[j] > tmpDis)
{
truckDis[j] = tmpDis;
q[tmpDis].enQueue(j);
}
}
}
}
printf("The highest possible quality is 1/%d.\n",sumDis-1);
return 0;
}

int main()
{
while(scanf("%d",&truckNum)&&truckNum)
{
getchar();
for(int i = 0;i < truckNum;i++)
gets(truckCode[i]);
search_Prim();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: