键盘输入一个高精度的正整数 n,去掉其中任意 s 个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的n 和 s,寻找一种方案使得剩下的数字组成的新数最小。
怎么样根据贪婪策略删除数字呢?总目标是删除高位较大的数字,具体的,相邻两位比较若高位比低位大,则删除高位。
C 代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Delete(char n[], int b, int k)
{
int i;
printf("11111 strlen(n)= %2d\n", strlen(n));
for(i=b; i<=strlen(n)-k; i=i+1)
n[i]=n[i+k];
}
int main( )
{ char n[100]="12435833";
int s=3,i,j,j1,c,data[100],len;
printf("%c ", n[8]);
len=strlen(n);
printf("$$$$$$$$$\n");
j1=-1; //记录上一个被删除的元素的位置,用来辨别是删除上一个被删除元素右边的元素还是左边的元素
for (i=0; i<s; i=i+1)
{ int len1=strlen(n);
for (j=0; j<len1-1; j=j+1)
if (n[j]>n[j+1]) //贪婪选择
{ Delete(n,j,1);
printf("##### j= %d j1= %d i= %d strlen(n)-1= %2d\n", j, j1, i, strlen(n)-1);
if (j>=j1) // 说明即将被删除的元素位于上一个被删除元素的右边
data[i]=j+i; //删除上一个被删除元素右边的元素 //记录删除数字位置
else //实例2向前删除的情况实例
data[i]=data[i-1]-1; 删除上一个被删除元素左边的元素
j1=j;
break;
}
printf("j= %d j1= %d i= %d len1= %d strlen(n)= %d\n", j, j1, i, len1, strlen(n));
if( j>=len1-1) //说明在给定的序列中,任意相邻的两个元素,总是后面的元素大于前面的元素,
break; //即序列中的元素是按照从小到大排列的, 一旦是这种情况,就直接从后向前删除 s 位数即可。
}
printf("Output *** data[]:\n");
for (int i=0; i<s; i=i+1)
printf("%2d ", data[i]);
printf("22222 strlen(n)= %2d len= %d i= %d\n", strlen(n), len, i);
for (i=i; i<s; i=i+1) //当序列中的元素是有序(从小到大排列)的, 直接从后向前删除 s 位数即可。
{ j=len-1-i;
Delete(n,j,1);
data[i]=j;
}
while (n[0]=='0' && strlen(n) >1)
Delete(n,0,1);
//将字符串首的若干个“0”去掉 print(n);
printf("Output array data[]:\n");
for (i=0; i<s; i=i+1)
printf("%2d ", data[i]);
printf("\n Output array n[]:\n");
printf("33333 strlen(n)= %2d\n", strlen(n));
for (i=0; i<strlen(n); i=i+1)
printf("%c ", n[i]);
system("pause");
return 0;
}
方法二:
int main( )
{ char n[100]="12435833";
int s=3,i,j,j1,c,data[100],len;
len=strlen(n);
printf("$$$$$$$$$\n");
j1=-1;
i=0;
j=0;
//n[-1]=
while (i<s && j< strlen(n)-1 )
{ //int len1=strlen(n);
printf("11111 j= %d j1= %d i= %d strlen(n)= %d\n", j, j1, i, strlen(n));
while (n[j]<=n[j+1])
j++;
if(j<strlen(n)-1)
{
Delete(n,j,1);
printf("22222 j= %d j1= %d i= %d strlen(n)= %d\n", j, j1, i, strlen(n));
if (j>=j1) // 说明即将被删除的元素位于上一个被删除元素的右边
data[i]=j+i; //删除上一个被删除元素右边的元素 //记录删除数字位置
else //实例2向前删除的情况实例
data[i]=data[i-1]-1;
printf("data[%d]= %d\n", i, data[i]);
i++;
j1=j;
j--;
if(j==-1) j=0;
//len1= strlen(n);
}
printf("33333 j= %d j1= %d i= %d strlen(n)= %d\n\n", j, j1, i, strlen(n));
}
printf("Output *** data[]:\n");
for (int i=0; i<s; i=i+1)
printf("%2d ", data[i]);
printf("22222 strlen(n)= %2d len= %d i= %d\n", strlen(n), len, i);
for (i=i; i<s; i=i+1) //当序列中的元素是有序(从小到大排列)的, 直接从后向前删除 s 位数即可。
{ j=len-1-i;
Delete(n,j,1);
data[i]=j;
}
while (n[0]=='0' && strlen(n) >1)
Delete(n,0,1);
//将字符串首的若干个“0”去掉 print(n);
printf("Output array data[]:\n");
for (i=0; i<s; i=i+1)
printf("%2d ", data[i]);
printf("\n Output array n[]:\n");
printf("33333 strlen(n)= %2d\n", strlen(n));
for (i=0; i<strlen(n); i=i+1)
printf("%c ", n[i]);
system("pause");
return 0;
}