贪心日:
问题1:删数问题
有一个长度为n(n <= 240)的正整数,从中取出s(s < n)个数,使剩余的数保持原来的次序不变,求这个正整数经过删数之后最小是多少。
输入:178543 4
样例输出:13
#include <bits/stdc++.h>
using namespace std;
int main()
{
char number[300];
int s;
int flag=1;
while(cin>>number>>s)
{
int length=strlen(number);
while(s!=0)
{
int i=0;
while(number[i]<=number[i+1])
{
i++;
}
while(i<length-1)
{
number[i]=number[i+1];
i++;
}
length--;
s--;
}
for(int i=0;i<length;i++)
{
if(number[i]=='0'&&flag==1)
{
continue;
}
else
{
cout<<number[i];
flag=0;
}
}
cout<<endl;
}
}
问题2:集合覆盖问题
得到NP难问题近似解的一种方法,时间从2的指数级降到n2级。
主要思路:不断选择包含最多内容的个体,直到需要被覆盖的集合中元素个数为0
POJ 1700 过河问题
非常经典的过河问题
若有abcd四人,速度递减,若要把cd送过河
1 ad过河,a回,ac过河,a回
2 ab过河,a回,cd过河,b回
选择两者中较小的即可
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int a[1005];
int main()
{
int number;
cin>>number;
while(number--)
{
int t;
cin>>t;
memset(a,0,sizeof(a));
for(int i=0;i<t;i++)
{
cin>>a[i];
}
sort(a,a+t);
int length=t;
int sum=0;
while(length)
{
if(length==1)
{
sum+=a[0];
break;
}
else if(length==2)
{
sum+=a[1];
break;
}
else if(length==3)
{
sum+=a[0]+a[1]+a[2];
break;
}
else if(length>3)
{
sum+=min(a[1]+a[0]+a[length-1]+a[1], a[length-1]+2*a[0]+a[length-2]);
length=length-2;
}
}
cout<<sum<<endl;
}
}
POJ1328 做过了
以每个海岛为圆心,半径为d画圆,交x轴于start end两点。以end为关键字升序排序。若下一个start小于end,则不需要新放置雷达,否则雷达+1
POJ1323
将其他人看做一组,自己看做一组,从最大数开始遍历。如果当前最大在自己手里,且对方没有牌来消耗最大数,那么就赢。