NOIP2004提高组

Posted Child-Single

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2004提高组相关的知识,希望对你有一定的参考价值。

T1津津的储蓄计划

题目链接

签到题,直接模拟:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int ans=0,now=0,ai[15],a;
    for(int i=1;i<=12;i++)scanf("%d",&ai[i]);
    for(int i=1;i<=12;i++)
    {
        a=ai[i];
        now+=300;
        if(now<a){printf("-%d",i);return 0;}
        int x=(now-a)/100*100;
        ans+=x;now-=x+a;
    }
    printf("%d",now+ans+(ans/5));
    return 0;
}
T1

T2合并果子

题目链接

优先队列(小根堆)直接贪心搞定:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
    int w;
    bool operator<(const node&x)const{return w>x.w;}
};
priority_queue<node>q;
int main()
{
    int n,a,ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a),q.push((node){a});
    for(int i=1;i<=n-1;i++)
    {
        node x1=q.top();
        q.pop();node x2=q.top();q.pop();
        ans+=x1.w+x2.w;q.push((node){x1.w+x2.w});
    }printf("%d",ans);
    return 0;
}
T2

T3合唱队形

题目链接

枚举每个点为中心,求出从左端和从右端的最长上升子序列长度之和,储存其最大值,再用总人数减去这个最大值即为答案:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
    int n,ti[105],f[105],f1[105],mxa=0,x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&ti[i]),f[i]=f1[i]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=i-1;j>=1;j--)
        if(ti[i]>ti[j])f[i]=max(f[i],f[j]+1);
    }
    for(int i=n;i>=1;i--)
    {
        for(int j=i+1;j<=n;j++)
        if(ti[i]>ti[j])f1[i]=max(f1[i],f1[j]+1);
    }
    for(int i=1;i<=n;i++)
    {
        x=f[i]+f1[i]-1;
        mxa=max(mxa,x);
    }
    printf("%d",n-mxa);
    return 0;
}
T3

T4虫食算

题目链接

本届NOIP提高组唯一有难度的题目,加剪枝的DFS即可解决,具体题解

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int maxn=36;
using namespace std;
char a[maxn],b[maxn],c[maxn],n;
int ans[200],q[maxn];
bool used[maxn];
bool ok(int x,int jin)
{
    if(ans[a[0]]+ans[b[0]]>=n)return 0;
    int i,j,k;
    for(i=x;i>=0;i--)
    {
        if(ans[a[i]]!=-1&&ans[b[i]]!=-1)
        {
            j=ans[a[i]]+ans[b[i]]+jin;jin=j/n;
            if(ans[c[i]]!=-1&&ans[c[i]]!=(j%n))return 0;
            if(ans[c[i]]==-1)
            {
                if(used[j%n])return 0;
                ans[c[i]]=j%n;used[j%n]=1;q[++q[0]]=c[i];
            }    
        }
        else break;
    }
    if(ans[a[0]]+ans[b[0]]>=n)return 0;
    for(;i>=0;i--)
    {
        if(ans[a[i]]!=-1&&ans[b[i]]!=-1)
        {
            j=ans[a[i]]+ans[b[i]];
            if(ans[c[i]]!=-1&&ans[c[i]]!=(j%n)&&ans[c[i]]!=((j+1)%n))return 0;
            if(ans[c[i]]==-1&&used[j%n]&&used[(j+1)%n])return 0;continue;
        }
        if(ans[a[i]]!=-1&&ans[c[i]]!=-1)
        {
            j=ans[c[i]]-ans[a[i]]+n;
            if(used[j%n]&&used[(j-1)%n])return 0;
        }
        if(ans[b[i]]!=-1&&ans[c[i]]!=-1)
        {
            j=ans[c[i]]-ans[b[i]]+n;
            if(used[j%n]&&used[(j-1)%n])return 0;
        }
    }
    return 1;
}
bool dfs(int x,int jin,bool flag)
{
    if(x<0)return 1;
    int p=q[0],i;
    if(flag)
    {
        if(ans[a[x]]!=-1)return dfs(x,jin,0);
        for(ans[a[x]]=n-1;ans[a[x]]>=0;ans[a[x]]--)
        {
            if(!used[ans[a[x]]])
            {
                used[ans[a[x]]]=1;
                if(ok(x,jin)&&dfs(x,jin,0))return 1;
                while(q[0]>p)
                {
                    used[ans[q[q[0]]]]=0;ans[q[q[0]]]=-1;
                    q[0]--;
                }
                used[ans[a[x]]]=0;
            }
        }
        return 0;
    }
    if(ans[b[x]]!=-1)return dfs(x-1,(ans[a[x]]+ans[b[x]]+jin)/n,1);
    for(ans[b[x]]=n-1;ans[b[x]]>=0;ans[b[x]]--)
    {
        if(!used[ans[b[x]]])
        {
            used[ans[b[x]]]=1;
            if(ok(x,jin)&&dfs(x-1,(ans[a[x]]+ans[b[x]]+jin)/n,1))return 1;
            while(q[0]>p)
            {
                int k=q[q[0]];used[ans[k]]=0;ans[k]=-1;q[0]--;
            }
            used[ans[b[x]]]=0;
        }
    }
    return 0;
}
int main()
{
    scanf("%d",&n);
    scanf("%s",a);
    scanf("%s",b);
    scanf("%s",c);
    for(int i=0;i<n;i++)ans[\'A\'+i]=-1;
    memset(used,0,sizeof(used));
    dfs(n-1,0,1);
    printf("%d",ans[\'A\']);
    for(int i=1;i<n;i++)printf(" %d",ans[\'A\'+i]);
    return 0;
}

noip2004虫食算
T4

 

以上是关于NOIP2004提高组的主要内容,如果未能解决你的问题,请参考以下文章

NOIP提高组2004 合并果子题解

虫食算 2004年NOIP全国联赛提高组(dfs)

1058 合唱队形 2004年NOIP全国联赛提高组

noip2004提高组题解

[NOIP2004提高组]虫食算

1058 合唱队形 2004年NOIP全国联赛提高组