回 帖 发 新 帖 刷新版面

主题:第30次编程比赛第2题

一系列整数 (a[1],a[2],a[3], ..., a[n]),如果 a[2]-a[1] = a[3]-a[2] = ... = a[n]-a[n-1],称它们是等差数列,现在给你一个整数数列,你需要替换其中的一些数使整个成为等差数列,但是每替换一个数需要付出相关代价 1,返回使整个数列成为等差数列的最小花费代价,如果所给的数列已经是等差数列返回 0。

比赛题目:

编写函数接口:

int howmany(int *a,int num)

其中 a 表示输入数列,其中任意的输入数列成员 a[k] 有 -10000<=a[k]<=10000,num 表示对应数列中成员总个数,3<= num <=50。

函数返回最小花费代价。

注意:
A、数列成员不允许被替换成小数(即最终必须是整数等差数列)。
B、可以修改数列 a 中成员值。(可以破坏原始输入)
C、任意替换后的成员 a[k] 可以是 a[k]<-10000 或者 a[k]>10000。(替换后值可以不遵守原始输入约束)

例子:

输入 a:{1,4,7,11}
num:4
返回:1

输入 a:{-10,-5,0,5,10,15}
num:6
返回:0

输入 a:{157, 119, 15, -5, -25}
num:5
返回:2

输入 a:{1,2,4,7,11,16,22,29,37,46,56,67,79,92,106}
num:15
返回:13

输入 a:{1,100,10,40,2,200,-71,250,99,103,325}
num:11
返回:7

回复列表 (共20个回复)

11 楼

#include<iostream.h>
int howmany(int *a,int num)
{
    int e=0,x;
    a=new int [num];
    int *b=new int [num-1];
    int *c=new int [num-1];
    cout<<"输入数组元素:" ;
    for(int r=0;r<num;r++)cin>>a[r];
    for(int t=0;t<num-1;t++)c[t]=0;
    for(int i=0;i<num-1;i++)b[i]=a[i+1]-a[i];
    for(int j=0;j<num-2;j++)
            if(b[j]==b[j+1])e++;
            if(e==num-1)x=0;
          for(int p=0;p<num-1;p++)
            for(int q=p;q<num-1;q++)if(b[p]==b[q])c[p]++;
            int d=c[0];
            for(int s=1;s<num-2;s++)if(d<c[s+1])d=c[s+1];
            s=num-d-1;
            
                     return s;
}
void main()
{
    int num,s=0;
    cout<<"输入数组的数目:";
    cin >>num;
    int *a=new int [num];
    s=howmany(a,num);
    cout<<"input"<<endl;
    cout<<s<<endl;
}

12 楼


#include<iostream>
#include<string>
using namespace std;

struct data{
    int sub;
    int i;
    int j;
};


int howmany(int *p,int num){
    data *q=new data[num];
    int *ch=new int[num];
    int max=0;
    memset(ch,0,num*4);
    int inc=0;
    for(int i=0;i<num;i++){
        for(int j=0;j<num;j++){
            if(j==i){
                q[j].sub=20001;
                continue;
            }
            if((p[i]-p[j])%(i-j)==0)
                q[j].sub=i>j?(p[i]-p[j])/(i-j):(p[j]-p[i])/(j-i);
            else
                q[j].sub=20001;
            q[j].i=i;
            q[j].j=j;
        }
        for(int mi=0;mi<num-1;mi++){
            if((q+mi)->sub==20001)
                continue;
            for(int j=0;j<num;j++){
                if((q+j)->sub!=20001&& (q+j)->sub==(q+mi)->sub)
                    ch[(q+j)->i]=ch[(q+j)->j]=1;
            }
            for(int k=0,count=0;k<num;k++){
                if(ch[k]==1)
                    count++;
            }
            max=(count>max)?count:max;
            memset(ch,0,num*4);
        }
        memset(q,0,num*12);
    }
    return num-max;
}

13 楼

#include <stdio.h>

#define Max 50

int howmany(int *a, int num)
{
    int max = 0;
    int gap;
    for(gap=num-1; gap>0; --gap)
    {
        int start;
        for(start=0; start<num; ++start)
        {
            int count = 1;
            int p;
            int x = a[start+gap] - a[start];
            if( x % gap != 0 )
                continue;
            x /= gap;  /* 目前等差数列的差为x */
            for(p=start+1; p<num; ++p)
            {
                if( a[p]-a[start] == x*(p-start) )
                    ++count;
            }
            if( count > max )
                max = count;
        }
    }
    return num - max;
}

int main()
{
    int a1[] = {1,4,7,11},
        a2[] = {-10,-5,0,5,10,15},
        a3[] = {157, 119, 15, -5, -25},
        a4[] = {1,2,4,7,11,16,22,29,37,46,56,67,79,92,106},
        a5[] = {1,100,10,40,2,200,-71,250,99,103,325};
    printf("%d\n", howmany(a1, 4));
    printf("%d\n", howmany(a2, 6));
    printf("%d\n", howmany(a3, 5));
    printf("%d\n", howmany(a4, 15));
    printf("%d\n", howmany(a5, 11));
    return 0;
}

14 楼

#include<iostream>
using namespace std;

typedef struct bnode //有序二叉树btree
{
    int data;
    struct bnode *lchild, *rchild;
} btree;

void Distroy(btree *b)//销毁有序二叉树b
{
      if (b)
      {
            Distroy(b->lchild);
            Distroy(b->rchild);
            delete b;
      }
}

btree* insert(btree *b, int x)//把x插入有序二叉树b
{
    if(b == NULL)
    {
        b = new btree;
        if(b == NULL)
        {
            puts("wrong");
            exit(1);
        }
        b->data = x;   //putchar(x);
        b->lchild = b->rchild = NULL;
    }
    else if(b->data == x)//不做任何插入操作
        ;
    else if(b->data > x)//把s所指结点插入到左子树中
       b->lchild = insert(b->lchild, x);
    else               //把s所指结点插入到右子树中
       b->rchild = insert(b->rchild, x);
    return b;
}

btree* search(btree *b, int x)//在有序二叉树b中寻找x
{
    if(b == NULL)
        return NULL;
    if(b->data == x)
        return b;
    if(b->data > x)
        return search(b->lchild, x);
    else
         return search(b->rchild, x);
}

int howmany(int *a, int num)//主要操作函数
{
      int min = num;//用来存储最小代价
      btree *cd = NULL; //有序二叉树b用来存储所有可能的公差

      for (int i=0; i<num-1; i++)//i表示第一个数的下标
      {
            for (int j=i+1; j<num; j++)//j表示第二个数的下标
            {
                  int d = (a[j]-a[i])/(j-i);//d表示包含第一个数和第二个数的等差数列的公差
                  int sum = 0;//累计花费代价
                  //如果该d为整数且第一次出现,累计以其为公差的数列所需花费代价
                  if (d*(j-i) == (a[j]-a[i]) && search(cd, d) == NULL)
                  {
                        cd = insert(cd, d);
                        for (int k=0; k<num; k++)//遍历数组,累计花费代价
                        {
                              if (a[k] != a[i]+(k-i)*d)
                                    sum++;
                              if (sum >= min)
                                    break;
                        }
                        if (sum < min)//存储最小代价
                              min = sum;
                  }
            }
      }
      Distroy(cd);

      return min;
}



int main(void)
{
      const int max = 11;
      int a[max] ={1,100,10,40,2,200,-71,250,99,103,325};

      int n = howmany(a, max);

      cout << n << endl;

      system("pause");
      return 0;
}

15 楼

// 最后形成的等差数列中,必然保留有至少两个原来的数列成员ai和aj (其中j>i)
// 而任意的一个数列可以由其中的两个数列成员ai和aj决定,
// 记等差数列成员为ai=a0+di,那么可以求出
//             d=(aj-ai)/(j-i)
//             a0=ai-d*i
// 因此,问题变为保留那两个成员才是最合适的
// 从数列a中,任意选择两个成员,这样就决定了一系列的数列new_a,
// 判断每个new_a和原来a中成员不相同的个数(实际上就是需要修改数列成员的个数),
// 记录下最小的不相同数目
// 新的数列中很有可能某些是一样的,这样子就会存在重复比较!
//#define MAX_NUM 10000
int howmany(int *a,int num)
{
    if(num<=2) return 0;
#ifndef MAX_NUM
    int ** arrTried =new int *[2];

    if(!arrTried)
        return -1;
    arrTried[0] = new int[num-1];
    arrTried[1] = new int[num-1];

    if(    !arrTried[0] || !arrTried[1])
        return -1;
#else
    int arrTried[2][MAX_NUM-1];
#endif

    int LestChange=num-2;

//    for(int i=0;i<num-1;i++)
    for(int i=num-2;i>=0;i--)
    {
        //当所给的刚好是等差数列时
        if(!LestChange)
            return 0;

        for(int j=i+1,nTryTimes=0;j<num;j++)
        {
            int temp1=a[j]-a[i];
            int temp2=j-i;

            if(temp1%temp2/*!=0*/)//最终必须是整数等差数列
                continue;

            //如果最终的数列中保留有原来的这个a[i]和a[j],则
            int d=temp1/temp2;
            int a0=a[i]-d*i;

            //判断当前a[i]和a[j]决定的数列是否和a[i]与a[j'](j'的取值为 0<=j'<=j-1)决定的数列是一样的,
            //一样的话,则表示已经比较过了。
            //这样子仅仅是减少了部分的重复比较而已!
            int k;
            for(k=0;(a0!=arrTried[0][k] || d!=arrTried[1][k]) && k<nTryTimes;k++)
            {
            }
            if(k!=nTryTimes)//找到重复
            {
                continue;
            }
            else
            {
                arrTried[0][nTryTimes]=a0;
                arrTried[1][nTryTimes]=d;
                nTryTimes++;
            }
            //比较由a0,d决定的当前数列和原来的数列之间成员不相同的个数
            int Change=0;
            for(int l=0,temp3=a0 ; l<num ; l++,temp3+=d)
            {
                if(a[l] !=temp3)
                    Change++;
                if(Change>=LestChange) break;
            }
            if(Change<LestChange)//记录下最小的不相同数目
                LestChange=Change;
        }
        
    }
#ifndef MAX_NUM
    if(arrTried)
    {
        if(arrTried[0])
            delete [] arrTried[0];
        if(arrTried[1])
            delete [] arrTried[1];

        delete [] arrTried;
    }
#endif
    return LestChange;
}

16 楼

int howmany(int *a, int num)
{
    int w = 0;
    int d = a[1] - a[0];
    int n1 = 0, n2 = 0;    

    for(int i = 1; i <= num - 1; i ++)
    {
        int dMax = a[i] - a[i - 1];
        for(int j = 1; j <= num - 1; j ++)
        {
            if(a[j] - a[j - 1] == dMax)
                n1 ++;
        }
        if(n1 > n2)
        {
            n2 = n1;
            w = i - 1;
        }
        n1 = 0;
    }

    int total = 0;
    d = a[w + 1] - a[w];
    for(int b = w + 2; b <= num - 1; b ++)
    {
        if(a[b] != a[b - 1] + d)
        {
            a[b] = a[b - 1] + d;
            total ++;
        }
    }
    for(int c = w - 1; c >= 0; c --)
    {
        if(a[c] != a[c + 1] - d)
        {
            a[c] = a[c + 1] - d;
            total ++;
        }
    }
    return total;
}

17 楼

18 楼

想看下内容,顶下

19 楼


void serch(int *a,int num,int p[50][50],int t,int eqs)
{
    int s,i,*rp;
    rp=new int[num-t-1];
    s=1;
    rp[0]=t;
    for (i=t+1;i<num;i++)
        if (((a[t]-a[i])/(i-t))==eqs)
            if ((a[t]-a[i])%(i-t)==0)
                rp[s++]=i;
    for (i=0;i<s-1;i++)
        for(int j=i+1;j<s;j++)    
            p[rp[i]][rp[j]]=s;
}

int howmany(int *a,int num)
{
    int p[50][50],i,s,j;
    for (i=0;i<num-1;i++)
    {
        for (j=0;j<num;j++)
            p[i][j]=0;
    }
    for (i=0;i<num-1;i++)
        for(j=i+1;j<num;j++)
            if (p[i][j]==0)
                if ((a[i]-a[j])%(j-i)==0)
                    serch(a,num,p,i,(a[i]-a[j])/(j-i));
                else p[i][j]=-1;
    s=p[0][1];
    for (i=0;i<num-1;i++)
        for(j=i+1;j<num;j++)
            if (s<p[i][j])
                s=p[i][j];
    cout <<s<<endl;
    return num-s;
}

20 楼

int howmany(int *a,int num)
{
 int b[50];
 int c[50];
 int i,j,def,t=0,cost=0;
 b[0]=c[0]=1;
 for (i=1;i<50;i++)
 {
  b[i]=0;
  c[i]=-1;
 }
 for (i=0;i<num-1;i++)
 {
   b[i]=a[i+1]-a[i];
 }
 
 for(i=0;i<num;i++)
 {
  
  for (j=0;j<i;j++)
  {
    if (b[j]==b[i])
    {   
        c[j]++;
        c[i]=0;
        break;
    }
    else 
        if(i!=0)
        c[i]=1;
  }
 }
 
 def=c[0];
 for (i=1;i<num-1;i++)
     
     if (c[i]>def)
     {
         def=c[i];
         t=i;
     }

for (i=t-1;i>=0;i--)
 {
   a[i]=a[i+1]-def;
   cost++;
 }

for (i=t+1;i<num;i++)
 {
      
  if (a[i]!=(a[i-1]+def))
  {
      a[i]=a[i-1]+def;
     cost++;

}

return cost;
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册