高精度整数去位取最小问题
2012-04-13 11:43 youxin 阅读(942) 评论(0) 编辑 收藏 举报Description
键盘输入一个高精度的正整数N,去掉其中任意M个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的N和M寻找一种方案使得剩下的数字组成的新数最小。输出组成的新的正整数。(不超过240位)
输入数据均不需判错。
如果去掉了某几个位后得到的新整数开头为0,保留0。
Input
本题有多组测试数据,每组测试数据占一行。
一个高精度正整数N(N不超过240位)一个正整数M。(M为不大于N的长度的正整数)
N,M由一个空格分开。
Output
新的正整数,每组数据的输出占一行。不要多余的空白.
Sample Input
456547 1 456547 2 456547 3 7773359 2 103 1
Sample Output
45547 4547 447 73359 03
本题可以贪心算法快速解决。
数据结构设计: 对于高精度整数,可以将其存储为字符串格式。
问题分析: 在位数固定前提下,让高位的数字尽量小。其值就较小。依据贪心策略可以解决这个问题。
如何根据贪心来删除数字呢?总目标是删除高位较大的数字,具体地相邻两位比较,若高位比地位大则删除高位.
但是看下面的特殊情况:
n3="1 2 3 4 5 6 7" s=3
经过对n3相邻位进行比较,一个数字也没删除,这就要将后3位删除。当然还有可以在相邻比较的过程中删除的位数小于s,也要进行相似的操作。
算法设计:
根据以上分析,算法注意由4部分组成:初始化,相邻数字比较(必要时删除),处理比较过程中删除位数不够s位情况和结果输出。
其中删除字符的实现方法很多:如
1.物理的进行字符删除,就是用后面的字符覆盖已删除的字符,字符串的长度改变,这样可能会有较多的字符移动操作,算法效率不高。
2.可以利用数字记录字符的存在状态,元素值为“1”表示对应的数值存在,0表示不存在。 但这样做前后数字的比较过程和最后的输出过程相对复杂些。
3,利用一个数组,来记录为删除字符的下标。删除值时对应数组的下标删除。
用C++的string类型很简单。代码如下:
#include<iostream> #include<string> using namespace std; string greedy(string &str,int n) { bool del; for(int i=n;i>0;i--) //这里为什么从n范围是从n到1,而不是从1到n,是为后面代码简化. { del=false; for(string::iterator it=str.begin();it!=str.end()-1;it++) { if(*it>*(it+1)) { str.erase(it); del=true; break; //为什么要跳出 } }//end for //如果所有数字递增,则删除最后几个数字直接返回 if(!del) { str.erase(str.end()-i,str.end()); break; } } return str; } int main() { string str; int n; cin>>str; cin>>n; cout<<greedy(str,n)<<endl; return 0; }
以1 2 4 3 为例,S=3;
最开始i=3; 进入里面的for循环后删除了4,退出for,变成了123
i=2; del=false;for循环没有元素删除,!del为真,表示此时是按照从小到大排列的,从后面删除i个元素.2 ,3变成1.
结果为1.
删除数组中第i个字符:
/*删除数组a【】的第k个字符 数组名不能用delete,c++的关键字*/
void del(char *a,int k) { while(a[k]!='\0') { a[k]=a[k+1]; k++; } } /*删除数组a【】从b起的k个字符 */ void del(char *a,int b,int k) { int i; for(i=b;i<=strlen(a)-k;i++) a[i]=a[i+k]; }
较简单的c算法:
#include<stdio.h> #include<stdlib.h> #include<string.h> void find() { char N[200]; int s; int i=0,j; printf("input the number:"); scanf("%s",N); printf("\ninput times:"); scanf("%d",&s); while(s>0) /*循环减s次*/ { i=0;/*每次删除后重头开始*/ while(i<strlen(N) && N[i]<=N[i+1])
i++;/*算法核心*/ for(j=i;j<strlen(N);j++)N[j]=N[j+1];/*移位将删除的覆盖*/ s--; } printf("%s",N); } int main() { find(); system("pause"); }
参考这里