【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

时间: 2024-11-01 13:45:27

【NOIP2004】提高组的相关文章

noip2004提高组题解

这次有两道题以前已经做过了,所以分数什么的也没有意义了.发现这年的难度设置极不靠谱,前三题都比较简单,最后一题太难,不知道出题人怎么想的. 第一题:储蓄计划 模拟. 第二题:合并果子 贪心.每次选最小的两堆合并. 第三题:合唱队形 两次动规.题目可以转化为找出一个人,使得以他为尾的最长上升子序列的长度最大,并且以他为首的最长下降子序列的长度也最大. 第四题:虫食算 马上想到搜索.但是规模太大,N可能有26位,如果简单枚举那么运算次数是26!≍4e27:剪枝方面只想到一个很弱的剪枝(对于26的规模

[NOIP2004] 提高组 洛谷P1092 虫食算

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用

[NOIP2004] 提高组 洛谷P1090 合并果子

题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了.多多在合并果子时总共消耗的体力等于每次合并所耗体力之和. 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力.假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最

[NOIP2004] 提高组 洛谷P1091 合唱队形

题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入输出格式 输入格式: 输入文件chorus.in的第一行是一个整数N(2<

[NOIP2004] 提高组 洛谷P1089 津津的储蓄计划

题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里,到了年末她会加上20%还给津津.因此津津制定了一个储蓄计划:每个月的月初,在得到妈妈给的零花钱后,如果她预计到这个月的月末手中还会有多于100元或恰好100元,她就会把整百的钱存在妈妈那里,剩余的钱留在自己手中. 例如11月初津津手中还有83元,妈妈给了津津300元.津津预计11月的花销是180元

【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]

以题写模板. 写了两个:n^2版本与nlogn版本 P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入输出格

[NOIP2004提高组]虫食算

题目:洛谷P1092.codevs1064.Vijos P1099. 题目大意:给你一个$n$进制.每个数都是$n$位的三个数a,b,c,这些数的数位由字母表示(共$n$个字母,从‘A’开始),所有数字都只对应一个字母,每个字母对应一个数字.现在知道a+b=c,求每个字母代表的数字,保证有且仅有一组解.解题思路:暴力,从后往前搜索每一列即可.注意传递进位.若一列知道了三个数,则判断是否合法,合法则继续搜索下一列.若一列知道了两个数,则可以推算出第三个数,若没被使用,则继续搜索下一列.若一列知道的

[NOIP2009] 提高组 洛谷P1073 最优贸易

题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息 之后,便决定在旅游的

洛谷P1063 能量项链 [2006NOIP提高组]

P1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标 记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记.因为只有这样,通过吸盘(吸盘是 Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量.如果前一颗能量珠的头标记为m,尾标记为r,后 一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为m*r*n(Mar