哎呀,好久没有更新博客啦,今天又刷了一波BC,而且又涨分,还是蛮开心的。
近来很多人告知了我的不足,我也渐渐体会到自己小题做的越来越好了,但是大题还是没有思路。
肯定是我光刷小题,不去学算法,大题也做的不多,结果才会这样。
虽说学算法是个日积月累的过程,但我看我要抓紧步伐,开始一些比较难一点的算法的学习了。
HDU-5499 SDOI
看不懂英文的同学去Bestcoder里面看中文版把(我估计英文版做出来是够呛的)
思路:这道题目不是特别难,但是特别烦,假设这不是一道中文题,让我用英文来看的话,我不知道自己还能不能很快做出来,甚至能不能做出来。我的话比较习惯用结构体排序。先读取数据,将两次最高的分数保存,如果遇到女性用flag记录。然后再计算一遍每个人的最终分数,排序!最后就是将最佳女选手挑出,如果flag记录了,那么就从前往后查找第一个女性选手。如果她在前m个,那么就不用移动;但是如果她不在前m个,那么就将她与第m个选手交换位置。输出答案!
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 100+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
struct man
{
char name[25];
int sex,r1,r2;
double r;
friend bool operator < (const man& A,const man& B)
{
return A.r > B.r;
}
}a[maxn];
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
int flag=0,ma1=0,ma2=0;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
{
char k[10];
scanf("%s %s %d %d",a[i].name,k,&a[i].r1,&a[i].r2);
ma1=max(ma1,a[i].r1);
ma2=max(ma2,a[i].r2);
if(k[0]=='m')a[i].sex=1;
else a[i].sex=0,flag=1;
}
for(int i=0;i<n;i++)
a[i].r=(1.0*a[i].r1/ma1)*300*0.3+(1.0*a[i].r2/ma2)*300*0.7;
sort(a,a+n);
if(flag)
{
for(int i=0;i<n;i++)
{
if(!a[i].sex)
{
if(i+1>m)
{
swap(a[i],a[m-1]);
}
break;
}
}
}
puts("The member list of Shandong team is as follows:");
for(int i=0;i<m;i++)
printf("%s\n",a[i].name);
}
return 0;
}
HDU- 5500 Reorder the Books
中文题意自己去搜吧~哈哈哈~~~
思路:比赛的时候还是比较机智的,一下就想出来O(N)的算法了。
官方题解太复杂了0 0, 我这里比较简单的说一下。
我们简单一想会发现不管是什么样的组合我们最多取n-1次就一定能将书排好序。
然后首先考虑编号最大的那个(因为编号最大的那个要放在最下面,我喜欢从下面来),判定最大编号的位置,那么最大编号下面的书是一定要被抽出来的(因为要把最大编号的放在最下面),那么我为什么不按照他们的编号顺序大小来抽,让他们放到上面的顺序是有序的,有这个考虑我就可以暂时不抽。然后我考虑次大编号的那本书(比最大编号小1的那本书),如果次大编号在最大编号的上面,那么次大编号的书是不用被抽走的,要抽走的只是在次大编号和最大编号之间的书,但是考虑到上面的思考我暂时不抽;如果次大编号在最大编号下面,那我现在抽走这本次大编号就是最机智的(次大编号书是早晚要抽走的,因为次大编号书不能在最大编号书的下面,如果先抽走别的书再抽走次大编号的书,两者相比较只是增加两本书之间的多余的书,反而费事了),那么这时次大编号书就是第一本了,按照刚才的理论,除了次大编号书与最大编号书之外的所有书都要被抽走,那么就相当于如果次大编号的书在最大编号书的下面,那么就不用看了,因为这时除了刚才选好的最大编号书,其他所有书都有被抽出,这样结束了。那么按照这个顺序,我的算法是从数组的尾开始往前寻找最大编号的,找到最大编号再找次大编号,以此类推,直至找到数组头,中途不回头。这时找到第几个编号,那么就至少需要操作几次。
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 100+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
int a[30];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
int k=n;
for(int i=n;i>=1;i--)
if(a[i]==k)k--;
printf("%d\n",k);
}
return 0;
}
HDU-5501 The Highest Mark
这道题容我在思考一下。。。