回复 12楼 ssr
解出来了~不过还没有优化(例如计算两段区间和可以用(K+1)*(K+1)的二维数组保存数据~这样每次读取数据就不用不断求和了)~
程序代码:
#include<stdio.h>
#include <limits.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
void Init(int** s,int** p,int** p_min,int* N,int* K); //初始化数据
void Print(int s[],int N); //输出数据
void Print_Result(int s[],int p_min[],int N); //输出执行结果
int Count(int s[],int i,int j); //求和
int Sqrt_Sum(int s[],int p[],int K); //求平方和
int fun_Main1(int s[],int p[],int p_min[],int N,int K);
int fun_Main2(int s[],int p[],int p_min[],int N,int K,int min);
int fun_1(int s[],int p[],int N,int K,int sum); //函数执行主体
int fun_2(int s[],int p[],int point,int r);
int fun_3(int s[],int p[],int point);
void Reserve(int s[],int p_min[],int N,int K); //数据倒置
void Swap(int*a ,int* b); //交换函数
int main()
{
int N=0;
int K=0;
int* s=NULL;
int* p=NULL;
int* p_min=NULL;
int min=0;
Init(&s,&p,&p_min,&N,&K);
puts("测试输入数据如下:");
Print(s,N); //开始检查初始化数据
min=fun_Main1(s,p,p_min,N,K);
puts("划分结果如下:");
Print_Result(s,p_min,N);
printf("最小平方和为%d\n",min);
free(s);
free(p);
free(p_min);
return 0;
}
void Init(int** s,int** p,int** p_min,int* N,int* K) //初始化数据
{
int i=0;
puts("请输入N K的值(中间用空格隔开):");
scanf("%d%d",N,K);
*s=(int*)malloc(*N*sizeof(int));
*p=(int*)malloc((*K+1)*sizeof(int));
*p_min=(int*)malloc((*K+1)*sizeof(int));
if (*s==NULL||*p==NULL||*p_min==NULL)
{
puts("分配空间失败!");
exit(0);
}
if (*N<=0||*K<=0||*N<*K)
{
puts("输入数据出错!");
exit(0);
}
printf("请输入%d个数:\n",*N);
for (i=0;i<*N;++i)
scanf("%d",&((*s)[i]));
for (i=0;i<*K;++i)
(*p)[i]=i;
(*p)[i]=*N;
memmove(*p_min,*p,(*K+1)*sizeof(int));
}
int Count(int s[],int i,int j) //求两个划分区间的和
{
int sum=0;
while (i<j)
sum+=s[i++];
return sum;
}
int Sqrt_Sum(int s[],int p[],int K) //求平方和
{
int i=0;
int sum=0;
for (i=0;i<K;i++)
{
int t=Count(s,p[i],p[i+1]);
sum+=t*t;
}
return sum;
}
int fun_Main1(int s[],int p[],int p_min[],int N,int K)
{
int min=INT_MAX;
int min1=0;
int min2=0;
while (1)
{
min1=fun_Main2(s,p,p_min,N,K,min);
Reserve(s,p_min,N,K);
if (min1<min)
{
memmove(p,p_min,(K+1)*sizeof(int));
min=min1;
}
min2=fun_Main2(s,p,p_min,N,K,min);
Reserve(s,p_min,N,K);
if (min2<min)
{
memmove(p,p_min,(K+1)*sizeof(int));
min=min2;
}
if (min1==min2)
break;
}
return min;
}
int fun_Main2(int s[],int p[],int p_min[],int N,int K,int min)
{
int sum=0;
int point=0;
while (1)
{
point=K-1;
sum=fun_1(s,p,N,K,sum); //sum为一个较优解
if (sum<min)
{
min=sum;
memmove(p_min,p,(K+1)*sizeof(int));
}
while (point>0&&p[point+1]-p[point]==1) //如果还没有完全遍历则需要继续比较
--point;
if (point==0)
break;
++p[point]; //这里移动一个指针继续比较
}
return min;
}
int fun_1(int s[],int p[],int N,int K,int sum) //函数执行主体
{
int i=0; //循环变量
int point=0;
while (1)
{
point=K-1; //每次重新遍历指针数据指向尾部
while (point>0&&(!fun_3(s,p,point)||p[point+1]-p[point]==1))
{
--point;
for (i=point+1;i<K&&point!=0;++i)
if (p[i+1]-p[i]>1&&fun_2(s,p,point,i))
{
point=K-1;
break;
}
}
if (point==0)
break;
while (p[point+1]-p[point]>1&&fun_3(s,p,point))
++p[point];
}
return Sqrt_Sum(s,p,K);
}
int fun_2(int s[],int p[],int point,int r)
{
int t=p[r]+1; //待划分数据的指针
int a1=Count(s,p[point-1],p[point]); //待定合并区间的左区间的值
int a2=Count(s,p[point],p[point+1]); //待定合并区间的右区间的值
int b1=0;
int b2=0;
int b3=Count(s,p[r],p[r+1]);
int c1=a1*a2;
int c2=0;
for (;p[r+1]-t>1;++t) //当划分区间长度大于1时
{
b1=Count(s,p[r],t); //b1为新划分区间
b2=Count(s,t,p[r+1]);
c2=b1*b2;
if (c1<c2)
{
int temp=p[point];
while (point<r) //对划分标记进行插入排序
{
p[point]=p[point+1];
++point;
}
p[point]=temp;
return 1; //如果划分标记有变动就要重新判断
}
}
return 0;
}
int fun_3(int s[],int p[],int point)
{
int a1=Count(s,p[point-1],p[point]);
int a2=Count(s,p[point],p[point+1]);
int b1=Count(s,p[point-1],p[point]+1);
int b2=Count(s,p[point]+1,p[point+1]);
return (a1*a1+a2*a2)>=(b1*b1+b2*b2);
}
void Reserve(int s[],int p_min[],int N,int K) //数据倒置
{
int i=0;
int j=0;
for (i=0,j=N-1;i<j;++i,--j)
Swap(&s[i],&s[j]);
for (i=1;i<K;++i)
p_min[i]=N-p_min[i];
for (i=1,j=K-1;i<j;++i,--j)
Swap(&p_min[i],&p_min[j]);
}
void Swap(int*a ,int* b) //交换函数
{
*a^=*b;
*b^=*a;
*a^=*b;
}
void Print(int s[],int N)
{
int i=0;
for (i=0;i<N;++i)
printf("%-4d",s[i]);
puts("");
}
void Print_Result(int s[],int p_min[],int N)
{
int i=0;
int j=1;
for (i=0;i<N;++i)
{
if (i==p_min[j])
{
printf("| ");
j++;
}
printf("%-4d",s[i]);
}
puts("");
}
[此贴子已经被作者于2017-4-19 14:16编辑过]