您的位置:首页 > 其它

HDU 2489 Minimal Ratio Tree【最小生成树】

2017-10-28 20:33 531 查看
题目链接

题目意思

给你n个节点,接着给出你这n个节点的权值,然后给出你节点之间连接的边的权值,现在给你一个数m,让你求包含m个节点的Ratio的最小值,其中Ratio就等于m个点的边权值之和比上节点权值和。

解题思路

这道题给出的节点数比较少,所以可以用深搜结合最小生成树来解。将所有的节点搜一遍,选出Ratio值最小的一个即可。用最小生成树求Ratio的值,在对每个点进行一次深搜,看该点选还是不选。

代码部分

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m;
int maps[20][20];
int node[20];///点的权值
int ans[20];
int vis[20];///标记数组
bool chose[20];///标记选还是不选
int dis[20];
double minn;

double prim(int f)
{
memset(vis,0,sizeof(vis));
for(int i=1; i<20; i++)
{
dis[i]=inf;
//vis[i]=0;
}
dis[f]=0;
//vis[1]=1;
int j,k,tmp,sum=0;
for(int i=1; i<=m; i++)
{
tmp=inf;
for(int j=1; j<=n; j++)
{
if(chose[j]&&!vis[j]&&tmp>dis[j])
{
tmp=dis[j];
k=j;
}
}
vis[k]=1;
sum+=dis[k];
//dis[k]=0;
for(int j=1; j<=n; j++)
{
if(chose[j]&&!vis[j]&&dis[j]>maps[k][j])
dis[j]=maps[k][j];
}
}
return sum*1.0;
}
void dfs(int p,int c)
{
if(c==m)
{
int first=0;
int countn=0;
double tem,tem1,tem2=0;
for(int i=1; i<=n; i++)
{
if(chose[i])
{
if(!first)
{
first=i;
tem1=prim(first);
}
tem2+=node[i]*1.0;
}
}
tem=tem1/tem2;
if(tem<minn)
{
minn=tem;
for(int i=1; i<=n; i++)
{
if(chose[i])
{
ans[countn]=i;///ans记录点的路径
countn++;
}
}
}
return;
}
chose[p]=1;
dfs(p+1,c+1);
chose[p]=0;
if(n-p+c>=m)
dfs(p+1,c);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
memset(chose,0,sizeof(chose));
minn=inf;
for(int i=1; i<=n; i++)
scanf("%d",&node[i]);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&maps[i][j]);
}
}
//cout<<'@';
dfs(1,0);
for(int i=0; i<m-1; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[m-1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: