k-means算法
#include<cstdio> #include<cmath> struct node { double x,y; int bl;//bl属性储存每个点属于哪个簇 }a[105],b[105],c[15];//a代表原始的点,b表示重新分配后的簇,c代表簇中心 double dist(node x,node y) { return sqrt( (x.x-y.x) * (x.x-y.x) + (x.y-y.y) * (x.y-y.y) ); } int main() { int n,k,t; scanf("%d %d",&n,&k); for(int i=1;i<=n;i++) { scanf("%lf%lf",&a[i].x,&a[i].y); a[i].bl=i; b[i]=a[i]; } /* for(int i=1;i<=k;i++)//指定初始簇中心 { scanf("%d",&t); c[i]=a[t]; } */ for(int i=1;i<=k;i++) c[i]=a[i];//不指定则使用前k个点做簇中心 while(1) { for(int i=1;i<=n;i++)//重新分配每个点所在的簇 { double dis=dist(b[i],c[1]); b[i].bl=1; for(int j=2;j<=k;j++) { if(dist(b[i],c[j])<dis) { dis=dist(b[i],c[j]); b[i].bl=j; } } } for(int i=1;i<=k;i++)//计算新的簇中心 { double sumx=0,sumy=0; int cnt=0; for(int j=1;j<=n;j++) { if(b[j].bl==i) { sumx+=b[j].x; sumy+=b[j].y; cnt++; } } c[i].x=sumx/cnt; c[i].y=sumy/cnt; } int flg=1; for(int i=1;i<=n;i++)//比较与上一轮分配结果是否有差异 { if(b[i].bl!=a[i].bl) flg=0; } if(flg) break; for(int i=1;i<=n;i++) a[i]=b[i]; } //for(int i=1;i<=n;i++) printf("%lf %lf %d\n",b[i].x,b[i].y,b[i].bl); for(int i=1;i<=k;i++) { printf("第%d个簇:",i); for(int j=1;j<=n;j++) { if(b[j].bl==i) printf("%d ",j); } printf("\n"); } return 0; } /* 样例数据: 8 2 1 1 2 1 1 2 2 2 4 3 5 3 4 4 5 4 */