贪心定义:
简单来说,贪心就是在所有方法中找到最优秀的方法;
例题:删数问题
- 一个高精度的正整数,去掉其中s个数后剩下的数按次序将数字组成的新数最小。
- 这个题要求删掉几个数,然后最小,很多人一定首先想到’sort’,然后挑大的数删。
- 但贪心往往就会因为考虑不周到而错的,有可能最优并没有考虑的,还有可能只过了样例但过不了特殊数据。像这一题,最优的方案应该是:满足(1.位数大2.数字大)这两个要求。
- 例如
- 15639;
2;
如果删最大数就变为了153;(先删9再删6)
但如果用后面的思路就变为了139;(先删6再删5)
153>139(后面是最优方案) - 总结一下,首先输入字符串(这题要用到高精度)输入s——删掉的个数,把字符串储存到a整型数组里;
- 接着循环s遍——如果删够了就停止了;里面也是一重循环枚举1到n——为了找到特殊情况;
- 判断特殊情况——两个位数较高的数,且前一个数大于后一个数,就删掉前一个数;
- 从头开始枚举新的数组,重复上一步;
- 最后要注意一点,一直不过可能就卡在这里了——前导零!!!
- 大体懂了思路,开始码代码
(一)输入
cin>>s1;
n=s1.size();
for(int i=0;i<=n;i++)//字符串从零开始
{
a[i+1]=s1[i]-'0';
}//字符串转数组的过程
//思想——s1[i]的ASCLL码减去'0'的ASCLL就是s1[i]的整型。
(二)核心代码
int m=n;
for(int i=1;i<=s;i++){//删去s个数
for(int j=1;j<=n;j++){//枚举每一个数
if(a[j]>a[j+1])//判断特殊情况
{
for(int l=j;l<=n-1;l++){//数组整体向前移动一位,删数
a[l]=a[l+1];
}
break;//从头再枚举一遍新的数组,重复删数
}
}
m--;//记录新的数组长度
}
(三)删除前导零
bool sub=0;
for(int i=1;i<=m;i++){
if(a[i]==0)
{
sub=0;//清零
for(int j=i-1;j>=0;j--){//从这个找到的零往前枚举判断
//是否为前导零
if(a[j]!=0&&a[j]!=-1) sub=1;
}
if(sub==0) a[i]=-1;//标记前导零
}
}
for(int i=1;i<=m;i++){
if(a[i]!=-1) cout<<a[i];//输出
}
- 以上为本题的解法,通过这题,我明白了贪心需要考虑周全,否则就是在做无用功。