C++:一个算法的实现

C++ : Implementation of an algorithm

本文关键字:一个 算法 实现 C++      更新时间:2023-10-16

我正在尝试实现以下算法:

  1. 创建具有单点P的集合Sp
  2. 计算Sp中的每个点与其外部的每个点之间的距离,然后将最大距离最小的点添加到Sp
  3. 重复2。直到Sp具有k个点
  4. 重复1-3,将每个点作为初始P
  5. 以最大距离最小的Sp为例

以下是我的代码:

using namespace std;
typedef pair<double,double> pairs ;
#define x first
#define y second    
#define INF numeric_limits<double>::infinity();
double dist(double x1,double y1,double x2,double y2)
{
return pow(((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)),1/2);
}

int main()
{
int n,k;      // n = total points, k= min points to be included
pairs a[n];
int vis[n]={0};
for(int i=0;i<n;i++)
cin>>a[i].x>>a[i].y;
set< pairs > s;
double ans=INF;
double least=INF;
int id=0;
for(int i=0;i<n;i++)
{
s.clear();
memset(vis,0,sizeof(vis));
while(s.size()<=k)          // till set has k points
{
s.insert(a[i]);
vis[i]=1;
for(auto v:s) // every point in set
{
for(int j=0;j<n;j++)  // point outside 
{
if(!vis[j])    
{
double d = dist(v.x,v.y,a[j].x,a[j].y);
if(d<=ans)           // compare and find least
{
ans=d;
id=j;
}
}
}
s.insert(a[id]);                // add least dist point
if(s.size()>=k)
break;
}
}

least=min(least,ans);
cout<<"least="<<least<<"n";
}

但代码被卡在了需要在集合中插入最小点的位置。它不是插入到Sp的最大距离最小的点。我不知道在实现中是否还有其他错误。

有人能检查一下这个实施并帮助纠正错误吗?

在您的代码中,ans默认设置为-1。如果我没有错的话,这永远不会发生:

if(d<=ans)           // compare and find least
{
ans=d;
id=j;
}

您只需重复插入[0]。

有人能检查一下这个实现并帮助纠正错误吗?

如果没有一组示例点,很难真正测试代码,但是。。。

(1) 以下部分是极其危险的

int n,k;      // n = total points, k= min points to be included
pairs a[n];
int vis[n]={0};
for(int i=0;i<n;i++)
cin>>a[i].x>>a[i].y;

我希望在你的真实代码中有这样的东西

static constexpr int n = <a n value>;
static constexpr int k = <a k value>;

或者至少,对于邪恶的宏,

#DEFINE n <a n value>
#DEFINE k <a k value>

因为,如果您定义了两个具有维度的C样式数组,则在运行时在两个变量中设置

pairs a[n];
int vis[n]={0};

您的代码不是C++标准。

此外,如果没有设置变量(如示例代码中所示),则行为是未定义的(也就是以有趣的方式崩溃)。

如果维度(kn)是在运行时设置的(根据标准输入?),则应该使用几个std::vector,而不是C样式数组;类似(注意:代码未测试)

int n;  // total points
int k;  // min points to be included
std::cin >> n;  // read n from standard input
std::cin >> k;  // read k from standard input
std::vector<pairs>  a   { n };
std::vector<int>    vis { n, 0 };
for ( int i = 0 ; i < n ; ++i )
std::cin >> a[i].x >> a[i].y;

(2) 如果您想退出带有k点的循环

while(s.size()<=k)          // till set has k points

你的while测试必须是s.size() < k,而不是s.size() <= k

否则,当size()k时,您仍处于循环中,您添加另一个点并使用k+1点退出

(3) 如果你想重复添加距离设置最小的点,下面的代码

while(s.size()<=k)          // till set has k points
{
s.insert(a[i]);
vis[i]=1;
for(auto v:s) // every point in set
{
for(int j=0;j<n;j++)  // point outside 
{
if(!vis[j])    
{
double d = dist(v.x,v.y,a[j].x,a[j].y);
if(d<=ans)           // compare and find least
{
ans=d;
id=j;
}
}
}
s.insert(a[id]);                // add least dist point
if(s.size()>=k)
break;
}

是错误的,因为

(3a)你没有将ans初始化为INF(你必须在每个点插入的周期之前初始化它,而不是在程序中只初始化一次)

(3b)必须将点插入for (auto v : s)循环之外,而不是内部

(3c)当在s中插入a[id]时,或者在下一个循环中再次插入相同的id时,必须设置v[id] = 1

(3d)在每次迭代时,您应该只插入a[i]一次,在while()循环之外,而不是在内部,一次又一次

(3e)不是错误,而是。。。您的周期for(auto v:s)不会修改v,因此,为了避免不必要的副本,为什么不修改for ( auto const & v : s )

(3f)不需要if(s.size()>=k) break;

记住第(2)点,我想你可以写一些类似的东西

s.insert(a[i]);
vis[i] = 1;
while ( s.size() < k ) // till set has k points
{
ans = INF;
for ( auto const & v : s ) // every point in set
{
for ( int j = 0 ; j < n ; ++j )  // point outside 
{
if ( ! vis[j] )    
{
double d { dist(v.x, v.y, a[j].x, a[j].y) };
if (d <= ans ) // compare and find least
{
ans = d;
id  = j;
}
}
}
}
s.insert(a[id]); // add least dist point
v[id] = 1;
}
相关文章: