NOIP 2010题解

唔..NOIP2010比较简单,总体感觉不错.

Problem 1: 机器翻译

水题,队列的简单应用.

读入时判断是否在内存中,可以用hash优化.如果不在内存中push进内存,放不下了pop header不用说了.上代码(未hash优化)

//Bazinga!
#include "cstdio"
int sum,i,m,n;
struct Q{
    int len,head,tail,qub[1001],i;
    void push(int n){
        qub[tail]=n;
        ++tail;
        if(len==m){
            ++head;
        }else{
            ++len;
        }
    }
    void has(int n){
        for(i=head;i<tail;++i){
            if(qub[i]==n){
                return;
            }
        }
        push(n);
        ++sum;
    }
} q;
int main(){
    scanf("%d%d",&m,&n);
    while(n--){
        scanf("%d",&i);
        q.has(i);
    }
    printf("%d", sum);
    return 0;
}

Click to see my ugly code.

hash优化版(不加也没关系...加了纯属多耗内存,但是在大数据前肯定要快.)

#include "cstdio"
int sum,i,m,n;
bool h[1001];
struct Q{
    int len,head,tail,qub[1001],i;
    void push(int n){
        h[qub[tail]=n]=true;
        ++tail;
        if(len==m){
            h[qub[head]]=false;
            ++head;
        }else{
            ++len;
        }
    }
    void has(int n){
        if(h[n]) return;
        push(n);
        ++sum;
    }
} q;
int main(){
    scanf("%d%d",&m,&n);
    while(n--){
        scanf("%d",&i);
        q.has(i);
    }
    printf("%d", sum);
    return 0;
}

DON‘T CLICK ME

Problem 2: 乌龟棋

非常经典的动态规划题目,不算难,但是对刚接触DP的人来说也不容易.

设$f[i,j,k,l]$为1格卡~4格卡各使用了i~l张能获得的最高分,则动规方程为

$f[i,j,k,l]=score[i+2j+3k+4l]+max\left( f[i-1,j,k,l],f[i,j-1,k,l],f[i,j,k-1,l],f[i,j,k,l-1]\right)$

边界条件$f[0,0,0,0]=score[0]$..

上代码:

//ug! So comfortable!
#include "cstdio"
int f[41][41][41][41],c[5],s[350],m,n,i,j,k,l;
int t1,t2,t3,t4,t5;
inline int mx(int a,int b){if(a>b){return a;}else{return b;}}
int main(){
    scanf("%d%d",&n,&m);
    for(i=0;i<n;++i){
        scanf("%d",&s[i]);
    }
    for(i=0;i<m;++i){
        scanf("%d",&j);
        ++c[j];
    }
    t1=c[1];
    t2=c[2];
    t3=c[3];
    t4=c[4];
    for(i=0;i<=t1;++i){
        for(j=0;j<=t2;++j){
            for(k=0;k<=t3;++k){
                for(l=0;l<=t4;++l){
                    t5=j+k+(l<<1);
                    t5<<=1;
                    if(i>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i-1][j][k][l]);
                    if(j>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i][j-1][k][l]);
                    if(k>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i][j][k-1][l]);
                    if(l>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i][j][k][l-1]);
                    f[i][j][k][l]+=s[t5+i+k];
                }
            }
        }
    }
    printf("%d", f[t1][t2][t3][t4]);
    return 0;
}

Don‘t touch me.

Problem 3: 关押罪犯

一道使用并查集的贪心算法题.输入所有怨气值,从大到小排序,一个个减小看有没有与现有的方案冲突;若冲突,输出当前怨气值,退出;不冲突,输出0.

一般解法是利用二分图二分答案,这样的时间复杂度是$\left( \text{It‘s really not clear. Depends on one‘s code.}\\ \text{There are many ways to implement the algorithm}\\ \text{and does not contains the same time complexity,}\\ \text{pretty sorry but I can‘t help.}\right)$.这样的想法很明确,但是不好写,而且慢.

用并查集写的,很短,很快,时间复杂度大约$\text{O}\left( \alpha\left( n\right) m\right)$.

顺便贴上我的代码:

#include "cstdio"
#include "algorithm"
using namespace std;
struct edge{
    int a,b,c;
    bool operator <(const edge x)const{
        return c>x.c;
    }
} e[100010];
int n,m,f[40020],x,y,t,p,i,j;
int find(int x){
    t=x;
    p=x;
    //find root
    while(t=f[t],t!=x){
        x=t;
    }
    //path compressing
    while(f[p]=t,p=f[p],p!=t){};
    return t;
}
int main(){
    scanf("%d%d",&n,&m);
    for(i=0;i<m;++i){
        scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
    }
    t=n<<1;
    for(i=0;i<=t;++i){
        f[i]=i;
    }
    sort(e,e+m);
    for(i=0;i<m;++i){
        x=find(e[i].a);
        y=find(e[i].b);
        if(x==y){
            printf("%d", e[i].c);//largest
            return 0;
        }
        f[y]=find(e[i].a + n);
        f[x]=find(e[i].b + n);
    }
    printf("0");
    return 0;
}

There is nothing more I could tell you..All right, others‘ code encourages man.

Problem 4: 引水入城

这是一道非常综合的题目,分两个小题.

1) 是否所有沙漠城市都有水供应. BFS即可
2) 最少需要多少个湖泊城市建立抽水站

而第 2) 小题仔细想又可以分为

2.1) 求每个湖泊城市覆盖的沙漠城市范围
2.2) 求如何用最少的线段覆盖整条线段

第一个BFS可过,用一种类似DP的方法亦可(这种方法存在反例,但是数据比较弱,除了第一个测试数据跑不过以外全可,非常快).
第二个贪心.

$\text{The final tip:}$

$\text{Be careful using DFS because of system stack overflow and it‘s performance loss.}\color{orange}{\text{YOU‘VE BEEN WARNED}}$

#include "cstdio"
#include "algorithm"
using namespace std;
struct edge{
    int a,b,c;
    bool operator <(const edge x)const{
        return c>x.c;
    }
} e[100010];
int n,m,f[40020],x,y,t,p,i,j;
int find(int x){
    t=x;
    p=x;
    //find root
    while(t=f[t],t!=x){
        x=t;
    }
    //path compressing
    while(f[p]=t,p=f[p],p!=t){};
    return t;
}
int main(){
    scanf("%d%d",&n,&m);
    for(i=0;i<m;++i){
        scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
    }
    t=n<<1;
    for(i=0;i<=t;++i){
        f[i]=i;
    }
    sort(e,e+m);
    for(i=0;i<m;++i){
        x=find(e[i].a);
        y=find(e[i].b);
        if(x==y){
            printf("%d", e[i].c);//largest
            return 0;
        }
        f[y]=find(e[i].a + n);
        f[x]=find(e[i].b + n);
    }
    printf("0");
    return 0;
}

Okay..It‘s wrong.

#include "cstdio"
#include "algorithm"
#define max(a,b) (a>b?a:b)
struct visitQueue
{
    short x[250000],y[250000];
    int h,t;
} vq;
#define pushq(xa,ya) vq.x[vq.t]=xa,vq.y[vq.t]=ya,++vq.t;
bool v[510][510];
int i,j,k,l,m,n,t,s;
int h[510][510],f[510][510];
struct range{
    int s,e;
} r[510];
bool cmp(range a,range b){
    return a.s<b.s;
}
void bfs(int x,int y){
    if(v[x][y]) return;
    vq.h=0;
    vq.t=1;
    vq.x[0]=x;
    vq.y[0]=y;
    v[x][y]=true;
    while(vq.h!=vq.t){
        i=vq.x[vq.h];
        j=vq.y[vq.h];
        k=h[i][j];
        if(i>1&&h[i-1][j]<k&&(!v[i-1][j])){
            v[i-1][j]=true;
            pushq(i-1,j);
        }
        if(i<m&&h[i+1][j]<k&&(!v[i+1][j])){
            v[i+1][j]=true;
            pushq(i+1,j);
        }
        if(j>1&&h[i][j-1]<k&&(!v[i][j-1])){
            v[i][j-1]=true;
            pushq(i,j-1);
        }
        if(j<n&&h[i][j+1]<k&&(!v[i][j+1])){
            v[i][j+1]=true;
            pushq(i,j+1);
        }
        ++vq.h;
    }
}
int main(){
    scanf("%d%d",&m,&n);
    for(i=1;i<=m;++i){
        for(j=1;j<=n;++j){
            scanf("%d",&h[i][j]);
        }
    }
 ///////////
 //   if(m==2&&n==5&&h[2][3]==6&&h[1][5]==3){
 //       printf("1\n1");//a hack for the first testing data. Remove this block
 //       return 0;
 //   }
 ///////////
    for(l=1;l<=n;++l){
        bfs(1,l);
    }
    t=0;
    for(j=1;j<=n;++j){
        if(!v[m][j]) ++t;
    }
    if(t>0){
        printf("0\n%d",t);
        return 0;
    }
    printf("1\n");
    for(j=1;j<=n;++j){
        if(h[m][j-1]<h[m][j] && j>1){
            f[m][j]=f[m][j-1];
        }else{
            f[m][j]=j;
        }
    }
    for(i=m-1;i>0;--i){
        for(j=1;j<=n;++j){
            f[i][j]=f[i+1][j];
            if(j>1 && h[i][j-1]<h[i][j] && f[i][j-1]<f[i][j]){
                f[i][j]=f[i][j-1];
            }
        }
    }
    for(j=1;j<=n;++j){
        r[j].s=f[1][j];
    }
    for(j=n;j>0;--j){
        if(h[m][j+1]<h[m][j]&&j<n){
            f[m][j]=f[m][j+1];
        }else{
            f[m][j]=j;
        }
    }
    for(i=m-1;i>0;--i){
        for(j=n;j>0;--j){
            f[i][j]=f[i+1][j];
            if(j<n&&h[i][j+1]<h[i][j]&&f[i][j+1]>f[i][j]){
                f[i][j]=f[i][j+1];
            }
        }
    }
    for(j=1;j<=n;++j){
        r[j].e=f[1][j];
    }
    std::sort(r,r+n,cmp);
    l=0;
    i=0;
    s=0;
    while(i<=n && s<n){
        if(r[i].s <= s+1){
            ++l;
            k=1;
            while(i<=n && r[i].s<=s+1){
                if(r[i].e>k){
                    k=r[i].e;
                }
                ++i;
            }
            s=k;
        }
    }
    printf("%d",l);
    return 0;
}

The code is this, exactly.

NOIP 2010题解

时间: 2024-10-20 07:23:29

NOIP 2010题解的相关文章

NOIP 2010 题解

[前言]最近这的很少弄OI了,虽说是暑假.趁要把NOIP2010~2013的题刷完,我做完一份便写一篇题解吧. [P1774机器翻译] P1774机器翻译 Accepted 标签:[显示标签] 描述 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译:如果内存中没有,软件就会在外存中的词典内查找,查出单

NOIP 2012 题解

[D1T1vigenere密码] P1778vigenere密码 Accepted 标签:[显示标签] 描述 16世纪法国外交家Blaise de Vigenère设计了一种多表密码加密算法--Vigenère密码.Vigenère密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用M表示:称加密后的信息为密文,用C表示:而密钥是一种参数,是将明文转换为密文或将密文转换为明文的算法中输入的数据,记为k. 在Vigenère

洛谷 P1525 关押罪犯==codevs 1069 关押罪犯[NOIP 2010]

P1525 关押罪犯 513通过 1.4K提交 题目提供者该用户不存在 标签图论并查集NOIp提高组2010 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 咳咳.竟MLE了. 囧.运行时错误,错误编号-… 点2是何方神圣? 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.

【noip 2010】 关押罪犯

描述 S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.如果两名怨气值为c的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c的冲突事件.每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S城Z市长那里.公务繁忙的Z市长只会去看列表中的第一个

NOIP 2014 题解

好吧,15年写14年题解,的确够晚的(P.S. 是因为我到现在才搞懂这些题) 正文之前,先膜拜膜拜一位大爷 %%% _debug 多膜拜膜拜 _debug 大爷,打程序时bug会减少哦 传送门: 生活大爆炸版石头剪刀布: http://codevs.cn/problem/3716/ 联合权值: http://codevs.cn/problem/3728/ 飞扬的小鸟: http://codevs.cn/problem/3729/ 无线网络发射器选址: http://codevs.cn/probl

历年NOIP选题题解汇总

联赛前上vijos板刷往年联赛题,使用在线编辑编写代码,祝我rp++. 废话不多说,挑比较有意思的记一下. 题目是按照年份排序的,最早只到了03年. 有些题目因为 我还没写/很早之前写的忘了 所以就先没写题解. NOIP2003 神经网络:按照题目怎么说怎么做,BFS即可.注意输出层是指出度为0的层,不是指深度最大的. 传染病防治:爆搜题,枚举每一层减掉哪个.复杂度不可算,大概在O(2^20*8!)强势不满,貌似卡不掉. NOIP2004 虫食算:知二推三,边搜边判. NOIP2005 过河:把

noip 2010 引水入城(dfs + 贪心)

非常感到抱歉,由于昨天有点忙,这道题的题解没写,今天补上,争取写的更加详细一点,让大家明白. 看一下题意: 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个NNN 行×M \times M×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度. 为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施.水利设施有两种,分别为蓄水厂和输水站.蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中. 因此,

noip 2010 三国游戏

三国游戏 三国游戏 描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有N 位武将(N为偶数且不小于4),任意两个武将之间有一个"默契值",表示若此两位武将作为一对组合作战时,该组合的威力有多大.游戏开始前,所有武将都是自由的(称为自由武将,一旦某个自由武将被选中作为某方军队的一员,那么他就不再是自由武将了),换句话说,所谓的自由武将不属于任何一方.游戏开始,小涵和计算机要从自由武将中挑选武将组

noip 2010 关押罪犯 (二分图染色 并茶几)

/* 二分图染色版本 两个监狱对应二部图的两部分 在给定的怨气值里二分 对于每一个Ci 进行染色判断是否合法 染色的时候 如果这条边的ci > Ci 这两个人就带分开 即染成不同的颜色 如果染色到某两个点颜色相同且怨气值>Ci 这个Ci就不合法 二分直到最后答案 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100