第一关——2005NOIP提高组

20:05:51   青春是挽不回的水,转眼消失在指尖。用力的浪费,再用力的后悔。——五月天《疯狂的世界》

第一题 谁拿了最多的奖学金

http://219.153.61.2:9000/contest/238/problem/1070

这道题重在打代码,适合用结构体,变量较多

#include<bits/stdc++.h>
using namespace std;
struct as{
    char st[20];
    int c;
    int j;
    char a;
    char b;
    int d;
    int jxj=0;
}ss[1003];
int main()
{
    int n,p,q,sum=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>ss[i].st;
        cin>>ss[i].c;
        cin>>ss[i].j;
        cin>>ss[i].a;
        cin>>ss[i].b;
        cin>>ss[i].d;
        if(ss[i].d>=1&&ss[i].c>80)ss[i].jxj+=8000;
        if(ss[i].c>85&&ss[i].j>80)ss[i].jxj+=4000;
        if(ss[i].c>90)ss[i].jxj+=2000;
        if(ss[i].c>85&&ss[i].b=='Y') ss[i].jxj+=1000;
        if(ss[i].j>80&&ss[i].a=='Y') ss[i].jxj+=850;
    }
    p=ss[1].jxj;
    for(int i=1;i<=n;i++)
    {
        if(ss[i].jxj>p)
        {
            p=ss[i].jxj;
            q=i;
        }
        sum+=ss[i].jxj;
    }
    cout<<ss[q].st<<endl<<p<<endl<<sum; 
    return 0; 
}

 像这种简单的题一定要仔细仔细再仔细!!!

21:41:23   如果 另个时空 另个身体 能不能 换另一种 结局  想见你 只想见你 未来过去 我只想见你  ——《想见你想见你想见你》

第二题 过河

http://219.153.61.2:9000/problem/1069

这道题是一道dp,但是如果只用简单的dp,就只能得到L<1000的那30分。首先,c++的空间复杂度是不支持数组开10^9这个大小的,其次,for循环后面的长度,时间复杂度也会超出范围,所以,这道题需要做一个优化。就是路径很长,但是石子数是很少的,而且青蛙最优走法是不走到石子的地方,所以只需要在路径的时候不断mod一次,就可以是程序大大优化。数组也没有必要开到10^9。

状态转移方程:f[i]=min(f[i],f[i-k]+vis[i]);

#include<bits/stdc++.h>
using namespace std;
int s,t,l,m,a[1000009],f[100009];
bool vis[100001];
int main()
{
    scanf("%d%d%d%d",&l,&s,&t,&m);
    for(int i=1;i<=m;i++)
    cin>>a[i];
    memset(f,60,sizeof(f));
    f[0]=0;
    int o=0;
    sort(a,a+m+2);
    for(int i=1;i<=m+1;i++) 
    {
        if(a[i]-a[i-1]<=t*s)
        o+=a[i]-a[i-1];
        else
        o+=(a[i]-a[i-1])%t+t;
        vis[o]=true;
    }
    for(long long i=1;i<=o+t;i++)
    { 
        for(int k=s;k<=t;k++)
        {
            if(i-k>=0)
            f[i]=min(f[i],f[i-k]+vis[i]);
        }
    }
    int ans=999999;
    for(int i=o;i<=o+t;i++)
    ans=min(ans,f[i]);
    printf("%d",ans);
    return 0;
}

22:20:30  背影是真的人是假的  没什么执着  一百年前你不是你我不是我  ——《百年孤寂》

第三题 篝火晚会【O(n)】

http://219.153.61.2:9000/problem/1068

这里并没有指这m个点必须是在一块的,只是说从原序列里找出了m个点进行交换,交换代价为m。这一点很坑,会想很久。

贪心:假设能够构成环,那么置换的代价一定可以等于所有不在位置上的数的个数。它原先一定不在自己的位置,因为一个位置的点只能有1个,而它已被某个点取到了。将初始序列的状态固定,枚举置换得到的序列,每次找一遍即可。

发现许多数都不会在位置上,这些状态都浪费了。于是对于置换得到的数列,找每个数距离初始状态的长,统计相同长的个数即可进行优化。

#include<bits/stdc++.h>
using namespace std;
const int N=50001;
int a[N],b[N];
int s[N],x[N],y[N],ans;
int i,j,n;
int main()
{
    scanf("%d",&n);
    for(i=1; i<=n; i++)
    scanf("%d%d",&a[i],&b[i]);
    s[1]=1,s[n]=a[1];
    s[2]=b[1];
    for(i=3;i<n;i++)
    if(a[s[i-1]]==s[i-2]) s[i]=b[s[i-1]];
    else s[i]=a[s[i-1]];
    for(i=1;i<=n;i++)
    {
        int t1=i+1,t2=i-1;
        if(t1>n) t1=1;
        if(t2<1) t2=n;
        if((s[t1]!=a[s[i]]||s[t2]!=b[s[i]])&&(s[t2]!=a[s[i]]||s[t1]!=b[s[i]]))
        {
            printf("-1");
            return 0;
        }
    }
    for(i=1;i<=n;i++)
    {
        x[(s[i]-i+n)%n]++;
        y[(s[i]+i-1)%n]++;
    }
    for(i=0;i<n;i++)
    {
        if (ans<x[i]) ans=x[i];
        if (ans<y[i]) ans=y[i];
    }
    printf("%d",n-ans);
    return 0;
}

23:07:51   世上无可代替是与你相拥的感受  人海里万中无一粒属于我的温柔  ——《一粒》

第四题  等价表达式

http://219.153.61.2:9000/contest/238/problem/1067

要对一个表达式求值,首先要干掉表达式外面包着的多余的括号。若表达式内不含任何符号,只有数字(或者是一个a),那么我们直接返回数字(或者a^1)。否则,找到优先级最低的且不被括号包着的运算符。找最右边一个(因为我们的运算符都是左结合的)。

很容易想到暴力拆括号。但是,这个方法有2个麻烦的地方

1.需要实现一个储存因式的结构体并支持多种操作

2.(a-1)^10^10^10^10等表达式会让结构体储存的东西多到爆炸。

一般这种表达式等问题通常都会通过用栈来解决

#include<bits/stdc++.h>
#define ll long long
#define oo 10020123
#define mod 100000007
using namespace std;
ll xz(ll x,ll t){
    ll ans=1;
    for(int i=1;i<=t;i++)
    ans=ans*x%mod;
    return ans;
}
ll sby(char *s,int l,int r,ll a)
{
    int o=0,mm=52,mn=+oo,cnt=0,p[52],num=0;
    memset(p,0x3f,sizeof(p));
    for(int i=r;i>=l;i--)
    {
        if(s[i]==')')o+=100;
        if(s[i]=='(')o-=100;
        if(s[i]=='^')p[i]=o+3,cnt++;
        if(s[i]=='*')p[i]=o+2,cnt++;
        if(s[i]=='+')p[i]=o+1,cnt++;
        if(s[i]=='-')p[i]=o+1,cnt++;
        if(mn>p[i])mn=p[i],mm=i;
    }
    if(cnt==0)
    {
        for(int i=l;i<=r;i++)if(s[i]=='a')return a;
        for(int i=l;i<=r;i++)if(isdigit(s[i]))num=num*10+s[i]-'0';
        return num;
    }
    else
    {
        if(s[mm]=='^')return xz(sby(s,l,mm-1,a),sby(s,mm+1,r,a));
        if(s[mm]=='*')return (sby(s,l,mm-1,a)*sby(s,mm+1,r,a))%mod;
        if(s[mm]=='+')return (sby(s,l,mm-1,a)+sby(s,mm+1,r,a))%mod;
        if(s[mm]=='-')return (sby(s,l,mm-1,a)-sby(s,mm+1,r,a))%mod;
    }
    return 0;
}
int main()
{
    int l[27],n,ans[15];
    char ss[27][52];    
    scanf("%[^\r]",ss[0]),getchar();
    l[0]=strlen(ss[0]);
    cin>>n,getchar();
    for(int i=1;i<=n;i++)
    {
        scanf("%[^\r]",ss[i]),getchar();
        l[i]=strlen(ss[i]);
    }
    for(int i=0;i<=10;i++)
    ans[i]=sby(ss[0],0,l[0]-1,i-5);
    for(int i=1;i<=n;i++)
    {
        int f=1;
        for(int j=0;j<=10;j++)
        if(ans[j]!=sby(ss[i],0,l[i]-1,j-5))
        {
            f=0;
            break;
        }
        if(f)
        printf("%c",'A'+i-1);
    }
    return 0;
}

好啦!!!大功告成!!!

23:53:31  是你带我找到另一个天堂  远比想象中更美  我们怀抱里的这一个天堂  每一个梦想 有无限的快乐  ——《另一个天堂》

猜你喜欢

转载自www.cnblogs.com/wybxz/p/12203803.html