noip2010提高组题解

NOIP2010提高组题解

T1:机器翻译

题目大意:顺序输入n个数,有一个队列容量为m,遇到未出现元素入队,求入队次数。

AC做法:直接开1000的队列模拟过程。

T2:乌龟棋

题目大意:有长度为n的棋盘,每个格子对应一个分数,1,2,3,4的卡片共m张,给出四种卡片各自的数量,求改变出牌顺序能获得的最大分数。

思路:开了一个四维的f[i][j][k][l]来表示每张牌有了几张时的最大分数;

F[i][j][k][l]=max(f[i-1][j][k][l],f[i][j-1][k][l],f[i][j][k-1][l],f[i][j][k][l-1])+a[i+2*j+3*k+4*l];

#include <iostream>
#include <memory.h>
using namespace std;

int n,m,a[355];
int c[125];
int num[5];
int f[51][51][51][51];

int main()
{
    cin >> n >> m;
    for (int i=1;i<=n;i++)
        cin >> a[i];
    for (int i=1;i<=m;i++)
    {
        cin >> c[i];
        num[c[i]]++;
    }
    for (int i=0;i<=num[1];i++)
        for (int j=0;j<=num[2];j++)
            for (int k=0;k<=num[3];k++)
                for (int l=0;l<=num[4];l++)
                {
                    if (i)
                        f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]);
                    if (j)
                        f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]);
                    if (k)
                        f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]);
                    if (l)
                        f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]);
                    f[i][j][k][l]+=a[i+2*j+3*k+4*l+1];
                }
    cout << f[num[1]][num[2]][num[3]][num[4]] << "\n";
}

T3:关押罪犯

题目大意:有n个罪犯要分到2个监狱,有的罪犯间结怨,如果怨气值为c就会发生影响为c的冲突。求最大冲突的最小值。

思路:用并查集来表示监狱,将冲突降序排序,冲突大的尽量分开,

直到矛盾,输出矛盾的冲突值即为最大。

#include <iostream>
#include <algorithm>
using namespace std;

int n,m;
struct node
{
    int a,b,c;
    bool operator < (const node &xx) const
    {
        return c<xx.c;
    }
}e[100011];
int x[40011];

int find(int ax)
{
    return x[ax]==ax?ax:x[ax]=find(x[ax]);
}

int main()
{
    cin >> n >> m;
    for (int i=1;i<=m;i++)
        cin >> e[i].a >> e[i].b >> e[i].c;
    sort(e+1,e+m+1);
    for (int i=1;i<=n*2;i++)
        x[i]=i;
    for (int i=m;i>=1;i--)
    {
        int fx=find(e[i].a);
        int fy=find(e[i].b);
        if (fx==fy)
        {
            cout << e[i].c << "\n";
            return 0;
        }
        x[fy]=find(e[i].a+n);
        x[fx]=find(e[i].b+n);
    }
    cout << 0 << "\n";
}

T4:引水入城

题目大意:有n*m的矩阵城市群。。。(→_→)第一排靠湖,第n排靠沙漠,每个城市海拔不同,沿湖城市可以造蓄水厂向海拔低的城市送水,求第n排能否都送到水。

(关于输出)       能:1             不能:0

(最少蓄水厂数)     (无水城市数)

思路:可以先bfs一次,如果最后一行没有全覆盖,顺便输出数量就可以结束了。如果全覆盖了,那么就对每个一线城市进行dfs求出它覆盖的n线城市的连续区间。最后进行区间覆盖。

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

int n,m;
int map[501][501];
int num;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
struct ct
{
    int x,y,h;
}tc,nw;
queue<ct> q;
int v[501][501];
struct xd
{
    int l,r;
}g[501];
int f[501];
int now;

void dfs(int ax,int ay)
{
    v[ax][ay]=1;
    if (ax==n)
    {
        g[now].l = min(g[now].l,ay);
        g[now].r = max(g[now].r,ay);
    }
    for (int i=0;i<4;i++)
    {
        int xx=ax+dx[i];
        int yy=ay+dy[i];
        if (xx>n||xx<1||yy>m||yy<1||map[ax][ay]<=map[xx][yy])
            continue;
        if (!v[xx][yy])
            dfs(xx,yy);
    }
}

int main()
{
    cin >> n >> m;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            cin >> map[i][j];
    for (int i=1;i<=m;i++)
    {
        tc.x=1;
        tc.y=i;
        tc.h=map[1][i];
        q.push(tc);
        v[1][i]=1;
    }
    while (!q.empty())
    {
        nw=q.front();
        q.pop();
        for (int d=0;d<4;d++)
        {
            tc.x=nw.x+dx[d],tc.y=nw.y+dy[d];
            if (tc.x<1||tc.x>n||tc.y<1||tc.y>m)
                continue;
            tc.h=map[tc.x][tc.y];
            if (!v[tc.x][tc.y] && tc.h<nw.h)
            {
                q.push(tc);
                v[tc.x][tc.y]=1;
            }
        }
    }
    int ans=0;
    for (int i=1;i<=m;i++)
        if (!v[n][i])
            ans++;
    if (ans>0)
    {
        cout << "0\n";
        cout << ans << "\n";
        return 0;
    }
    cout << "1\n";
    for (int i=1;i<=m;i++)
    {
        memset(v,0,sizeof(v));
        now=i;
        g[now].l=m+1;
        g[now].r=0;
        dfs(1,i);
    }
    f[0] = 0;
    for (int i=1;i<=m;i++)
    {
        f[i]=1<<30;
        for (int j=1;j<=m;j++)
            if (i>=g[j].l && i<=g[j].r)
                f[i]=min(f[i],f[g[j].l-1]+1);
    }
    cout << f[m] << "\n";
}
时间: 2024-10-25 07:34:22

noip2010提高组题解的相关文章

noip2004提高组题解

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

NOIP2010提高组乌龟棋 -SilverN

题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点. 乌龟棋中M张爬行卡片,分成4种不同的类型(M张卡片中不一定包含所有4种类型的卡片,见样例),每种类型的卡片上分别标有1.2.3.4四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数.游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前

noip2003提高组题解

这一年的前三题虽然难度不高,但是第二题极为繁琐,想在考场上用较短的时间拿到第二题的分数难上加难.所以必须要调整策略,争取拿其他三题的分数.第四题是比较普通的搜索题,分数比较好拿,但是很容易想成树形DP,就只能拿30~50分. ? 第一题:神经网络 模拟 有几个注意点: 输入层(即第一层)的结点的U(阈值)是没有用的: 题目说输出「最后状态非零的输出层神经元状态」,但实际上输出的是状态大于0的值. 由于没有注意到神经元只有在兴奋状态时才会向下传送信号,所以WA了1次. ? 第二题:侦探推理 模拟+

noip2000提高组题解

事实再次向我证明了RP的重要性... 第一题:进制转换 是我最没有把握AC的一道题目却是我唯一一道AC的题目,真是讽刺.看完题目几乎完全没有往正常的解法(取余倒序)去想,直接写了搜索,因为数据范围在2^16,感觉枚举每一位上的数应该就够了,但是在自己的电脑上连样例都用了3.4s,然后想不到任何有效的剪枝,就果断放弃了.最后写完其他三题之后还是回过头看了下这道题,还是没往正常的解法想....结果惊人地AC了...RP真的太重要了. 然后经提醒终于想到了正常一点的解法,查了网上的题解之后开始自己写取

NOIP 2014 提高组 题解

NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法,直接模拟,别读错题. 1 int wn[5][5]={{2,0,1,1,0}, 2 {1,2,0,1,0}, 3 {0,1,2,0,1}, 4 {0,0,1,2,1}, 5 {1,1,0,0,2}}; 6 7 int n,na,nb; 8 int a[222],b[222]; 9 int s1,s

NOIP2007 提高组 题解

2007 提高组题解 第一题 一开始还想是不是要用哈希表储存呢,但仔细想了一会儿,那个数据量20W 用个快排序,时间是能过的.所以这道题用个STL的快排,再一个循环统计个数就OK了.但最后交上去评测时0分,很尴尬.就是我在数据初始化时从一开始计数,我循环又从一开始,你懂的,多算了一次,爆掉了.改了就100了.200W的话数据就很强了,用哈希好一些. 第二题 额,写得很快,果然这种无脑模拟题最适合我了.但自信没检查,带了3组给的数据就走了.果然错了,过了4个点好像.主要是题没读完,没有判断处于字母

noip2009提高组题解

第一题:潜伏者 模拟 注意点: 不同的密文对应的明文不同,反过来,不同的明文对应的密文也不同,我用了两个hash表来实现: 26个明文字母必须有对应的密文字母,我用了两个计数变量来判断是否26个字母都有匹配. ? 第二题:Hankson的趣味题 数论 对 a0, a1, b0, b1 四个数进行质因数分解,然后确定 x 的各质因数的指数的取值范围,运用乘法原理解决.详细分析见下: (引用自http://wenwen.sogou.com/z/q169562042.htm) Gcd(x,a0)=a1

noip2001提高组题解

今天继续感动滚粗.第一次提交170分,不能多说. 第一题:一元三次方程 明明是寒假讲分治的时候做过的题居然还是WA而且只拿了60分,说明知识掌握实在不够牢固. 寒假做的是保留4位小数,原题只保留2位,又因为答案在[-100,100],所以直接枚举-10000到10000即可. 然后鉴于寒假的时候写的二分,我就傻X兮兮地在循环里面写了个二分...尼玛经验害死人啊...更可怕的是题目的hint里也明显地提示了二分...然后我就逗比了. 提交4次AC . 第二题:数的划分 去年学回溯的时候就做过,所以

NOIP2010提高组 关押罪犯 -SilverN

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