本周的贪心算法的代码基本在听完课后把保存的进行了修改,发现自己原本的代码是这么的麻烦。
首先是本周积累知识
下标储存;举例寻找规则(公式);两个问题合为一个
首先是删数问题,一开始认为删除当中最大的就可以,之后举例发现不行。然后经过多次举例发现在此类数字串中,如果删去的是第一个递减区间的第一个数就可以尽可能地控制它,也就是将其前面较大的删去,让后面较小的顶上。
代码实现环节中要用size计算长度,以便将其变短。
PS:使用string类最好,因为长度可以任意输入,但截止到空字符。
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
string a;
int k;
cin>>a>>k;
int len=a.size();
while(k--)
{
for(int i=0; i<len; i++)
if(a[i]>a[i+1]||i==len-1)
{
a.erase(i,1);
break;
}
}
cout<<a<<endl;
}
}
第二题是寻找平面上的极大点
本题的意思我也是读了很多遍才理解,本质就是如果大于其y值得都在左边,小于其y值得都在右边,即为最大值。
最好的方式就是用struct语句输入坐标点。
然后将其x从小到大排序,x相同的点按照y坐标从小到大排序。如此一来在排序内就形成了一个个小区域,在小区域内y最大就为极大点,已知最后一个为极大点,向前推进,如果出现第一个x大于后面的极大点x即为第二个极大点。
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
struct point
{
int x,y;
};
bool cmp(point a,point b)
{
if(a.x!=b.x)
return a.x<b.x;
else
return a.y<b.y;
}
int main()
{
point a[110];
int n;
int i;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i].x>>a[i].y;
}
sort(a+1,a+n+1,cmp);
int max=0;
int t=0;
int b[110];
for(i=n;i>=1;i--)
{
if(a[i].y>max)
{
t++;
b[t]=i;
max=a[i].y;
}
}
for(i=t;i>1;i--)
{
printf("(%d,%d),"a[b[i]].x,a[b[i]].y);
}
printf("(%d,%d)",a[b[i]].x,a[b[i]].y);
return 0;
}
第三题为拼点游戏
具体类型如同田忌赛马,自己最好的打不过对方的最好的就用最差的消耗掉,然后比第二好的。
本题思路是先判断自己最好的是否能打过对方的最好的,如果不能,就看自己最小的是否能打过对方最小的,如果不能,就看自己最小的能否打过对方最好的,最后用自己最小的消耗掉对方最好的。
本体本质即为能赢就赢。
ps:此题陷阱是求一个最大,一个最小。
求最大写完之后,发现写不出来最求最小,之后老师讲了,都求最大才恍然大悟,用最大减去最小就行。本题一直wrong。
#include<iostream>
#include<algorithm>
using namespace std;
int a[1010], b[1010];
int n;
int solve(int a[], int b[])
{
int choco= 0;
int begina= 0, enda= n-1, beginb = 0, endb= n-1;
while (begina<=enda&&beginb<=endb)
{
if (b[endb] > a[enda])
{
endb--;
enda--;
choco+= 3;
}
else if (b[beginb ] > a[begina])
{
begina++;
beginb ++;
choco += 3;
}
else if (b[endb] == a[enda])
{
beginb ++;
enda--;
choco+= 2;
}
else
{
enda--;
beginb ++;
choco++;
}
}
return choco;
}
int main()
{
while (cin>>n&&n!=0)
{
for (int i = 0; i< n; i++)
cin >> a[i];
for (int i = 0; i< n; i++)
cin >> b[i];
sort(a, a + n);
sort(b, b + n);
int max=solve(a, b);
int min=4*n-solve(b,a);
cout<<max <<' '<<min<<endl;
}
return 0;
}
第四个问题为过河问题
总的来说有两个方法,首先是最快的挨个送,第二个就是,按照头头尾尾的方式送之后头尾再送。t[0]+2t[1]+t[n-1];2t[0]+t[n-2]+t[n-1]不断比较这两个当中的最小的就可以
ps:一定要判断还剩几个人,因为公式不支持低于三人的,应当另行计算。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[1010],t,n,sum;
cin>>t;
while(t--)
{
cin>>n;
sum=0;
for(int i=0; i<n; i++)
cin>>a[i];
sort(a,a+n);
while(n>3)
{
sum=min(sum+a[1]+a[0]+a[n-1]+a[1],sum+a[n-1]+a[0]+a[n-2]+a[0]);
n-=2;
}
if(n==3)
sum+=a[0]+a[1]+a[2];
else if(n==2)
sum+=a[1];
else
sum+=a[0];
cout<<sum<<endl;
}
}