这里是第一题的题干:https://www.luogu.org/problemnew/show/P1093
这道题,就是一道简单的排序,在这里,我用的是快速排序,根据题目的要求去进行排序即可。
直接暴力上代码~~~
#include<iostream>
#include<cstdlib>
#include<utility>
#include<cstdio>
using namespace std;
struct score{
int yu,shu,yin,hao;
}a[500];
int n,num[500];
void qsort(int l,int r)
{
if(l>=r)
return;
int k=rand()%(r-l+1)+l;
int t=num[k],s=a[k].yu,h=a[k].hao;
int i=l,j=r;
while(i<=j){
while(num[i]>t||(num[i]==t&&a[i].yu>s)||(num[i]==t&&a[i].yu==s&&a[i].hao<h))i++;
//先看总分的高低,再看语文分数的高低,如果还是相同的话,就看谁的学号在前面
while(num[j]<t||(num[j]==t&&a[j].yu<s)||(num[j]==t&&a[j].yu==s&&a[j].hao>h))j--;
//这里也是一样的
if(i<=j){
swap(a[i],a[j]);
swap(num[i],num[j]);
i++;
j--;
}
}
qsort(l,j);
qsort(i,r);
}
int main()
{
freopen("scholar.in","r",stdin);
freopen("scholar.out","w",stdout);
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i].yu>>a[i].shu>>a[i].yin;
num[i]=a[i].yu+a[i].shu+a[i].yin;
a[i].hao=i;//第几个输入的,学号就是几
}
srand(1000000);
qsort(1,n);
for(int i=1;i<=5;++i)
cout<<a[i].hao<<" "<<num[i]<<endl;
return 0;
}
这是第二题:https://www.luogu.org/problemnew/show/P1094
这道题,首先,我们先将所有的纪念品的价值从高到低排一下序。然后使用贪心的做法,考虑当前没有分组的最大价值的纪念品能否与当前最小的纪念品配对(二者的价值和不大于规定的额度)。如果不行,那么这个大的单独一组,如果可以,那么这个最大的和最小的一组。
具体实现代码里的注释会有的~~~
#include<iostream>
#include<cstdlib>
#include<utility>
#include<cstdio>
using namespace std;
int w,n,a[30010];
int le,ri,ans=0;
void qsort(int l,int r)
{
if(l>=r)
return;
int t=a[rand()%(r-l+1)+l];
int i=l,j=r;
while(i<=j){
while(a[i]<t)i++;
while(a[j]>t)j--;
if(i<=j){
swap(a[i],a[j]);
i++;
j--;
}
}
qsort(l,j);
qsort(i,r);
}
void findans()
{
le=1,ri=n;
while(le<=ri)
{
if(a[le]+a[ri]<=w){//le是当前没有分组的最大价值,ri是最小值
le++;
ri--;
ans++;
}
else{
ri--;
ans++;
}
}
}
int main()
{
freopan("group.in","r",stdin);
freopan("group.out","w",stdout);
cin>>w>>n;
for(int i=1;i<=n;++i)
cin>>a[i];
srand(1000000);
qsort(1,n);//从大到小排序
findans();
cout<<ans<<endl;
return 0;
}
这里是第三题:https://www.luogu.org/problemnew/show/P1095
这道题,其实有一点水。。。就是一个最简单的动态规划再加上贪心的做法。
具体实现就直接看代码吧:
#include<iostream>
#include<cstdio>
using namespace std;
int f[300100];
int main()
{
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
int m,s,t;
cin>>m>>s>>t;
//这里是闪烁法术的情况
for(int i=1;i<=t;i++){
if(m>=10){
f[i]=f[i-1]+60;
m-=10;//如果能用,就用
}
else{
f[i]=f[i-1];
m+=4;//否则就在原地休息
}
}
//这里是跑步的情况
for(int i=1;i<=t;i++){
f[i]=max(f[i],f[i-1]+17);//dp[i]为使用法术和跑步的最大值(最优)
if(f[i]>=s){
cout<<"Yes"<<endl<<i<<endl;//如果超过了距离s,就成功了,输出Yes
return 0;
}
}
cout<<"No"<<endl<<f[t]<<endl;//没成功,输出No就好了~~~
return 0;
}
这个是第四题:https://www.luogu.org/problemnew/show/P1096
这道题,有点简单了吧。。。就是一道普普通通的汉诺塔问题,乘了个二,然后再用高精度实现不就好了吗?
直接暴力上代码~~~
#include<iostream>
#include<cstdio>
using namespace std;
int l,n;
int a[201],b[201];
void multiply()
{
int t=0;
for(int i=200;i>=1;i--){
l=b[i]*2+t;
b[i]=l%10;
t=l/10;
}
}//高精度乘法
void add()
{
int t=0;
for(int j=200;j>=1;j--){
l=a[j]+b[j]+t;
a[j]=l%10;
t=l/10;
}
}//高精度加法
int main()
{
freopen("hanoi.in","r",stdin);
freopen("hanoi.out","w",stdout);
cin>>n;
b[200]=1;
for(int i=1;i<=n;i++){
multiply();
add();
}
int k=1;
while(a[k]==0&&k<200)
k++;
for(int i=k;i<=200;i++)
cout<<a[i];
return 0;
}

本文详细解答了NOIP2007年普及组的四道题目,涉及快速排序、贪心策略和动态规划等算法。第一题采用快速排序解决排序问题;第二题通过贪心思想,对纪念品按价值排序后尝试配对;第三题是结合动态规划与贪心的简单问题;第四题为汉诺塔问题的变种,利用高精度计算求解。
1152

被折叠的 条评论
为什么被折叠?



