ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

noip2013 提高组部分题解

2019-03-06 11:48:58  阅读:259  来源: 互联网

标签:ch noip2013 格子 int 题解 提高 位置 空白 棋子


P1440 [noip2013]积木大赛

题目

LUOGU 1969

描述 Description
春春幼儿园举办了一年一度的“积木大赛”。今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1且高度不定的积木组成,第i块积木的最终高度需要是hi。
在搭建开始之前,没有任何积木(可以看成n块高度为 0 的积木)。接下来每次操作,小朋友们可以选择一段连续区间[L, R],然后将第L块到第R块之间(含第L块和第R块)所有积木的高度分别增加1。
小M是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少。但她不是一个勤于动手的孩子,所以想请你帮忙实现这个策略,并求出最少的操作次数。
输入格式 Input Format
输入包含两行:
第一行包含一个整数n,表示大厦的宽度。
第二行包含n个整数,第i个整数为hi。
输出格式 Output Format
仅一行,即建造所需的最少操作数。
样例输入 Sample Input
5
2 3 4 1 2
样例输出 Sample Output
5
时间限制 Time Limitation
1s
注释 Hint
【样例解释】
其中一种可行的最佳方案,依次选择
[1,5]  [1,3]  [2,3]  [3,3]  [5,5]
【数据范围】
对于 30%的数据,有1 ≤ n ≤ 10;
对于 70%的数据,有1 ≤ n ≤ 1000;
对于 100%的数据,有1 ≤ n ≤ 100000,0 ≤ hi ≤ 10000。
来源 Source
noip2013

代码

#include<bits/stdc++.h>
#define _ 100010
using namespace std;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
	return num*f;
}
int n,a[_],ans;
int main()
{
	memset(a,0,sizeof(a));
	n=read();
	for (int i=1;i<=n;++i)
	{
		a[i]=read();
		if (a[i]>a[i-1]) ans+=a[i]-a[i-1];
	}
	printf("%d",ans);
	return 0;
}

糖块

题目

描述 Description
现在有n(1 <= N <= 1,000,000, N 是奇数)个盒子,编号是1…n。
数学老师为了惩罚他,决定让他做一个难题,他让小x会对这些盒子做k(1 <=k <= 25,000)次放糖块的操作(这得多少糖块呀)。
数学老师每次会给小x一个区间[a,b],这时小x就会从编号是a的盒子到编号是b的盒子每个盒子都放一个糖块。
做完k次操作后,数学老师会问小x,在所有盒子的糖块个数中,这些糖块个数的中位数是多少。(最中间的值)。
因为n是奇数,所以这个答案肯定是唯一的。
输入格式 Input Format
第一行:两个整数 n k。
接下来k行,每行一个区间 ai bi ,表示要放糖块的区间。
输出格式 Output Format
一个整数,表示中位数的值。
样例输入 Sample Input
7 4
5 5
2 4
4 6
3 5
样例输出 Sample Output
1
时间限制 Time Limitation
注释 Hint
【样例解释】一共有7个盒子,4个操作,第一次在5号盒子里放1个,第二次在2 3 4号盒子里放。etc
放完糖块之后,盒子里的糖块依次是0,1,2,3,3,1,0.排过序后,数字1是中位数。
【数据范围】
50%数据保证 n,k<=5000.
来源 Source
usaco 2011 stacking

代码

#include<bits/stdc++.h>
#define _ 1000100
using namespace std;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
	return num*f;
}
int n,k;
int a[_];
int main()
{
	n=read(),k=read();
	for (int i=1;i<=k;++i)
	{
		int x=read(),y=read();
		a[x]++,a[y+1]--;
	}
	for (int i=1;i<=n;++i)
		a[i]+=a[i-1];
	sort(a+1,a+n+1);
	printf("%d",a[n/2+1]);
	return 0;
}

P1442 [noip2013]华容道

题目

LUOGU 1979

描述 Description
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
1.   在一个 nm 棋盘上有 nm 个格子,其中有且只有一个格子是空白的,其余 nm-1 个格子上每个格子上有一个棋子,每个棋子的大小都是 11 的;
2.   有些棋子是固定的,有些棋子则是可以移动的;
3.   任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。
游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。  
给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EX[i] 行第 EY[i] 列,指定的可移动棋子的初始位置为第 SX[i] 行第 SY[i] 列,目标位置为第 TX[i] 行第 TY[i] 列。
假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请
你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。
输入格式 Input Format
第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;
接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。
接下来的 q 行,每行包含 6 个整数依次是 EX[i]、EY[i]、SX[i]、SY[i]、TX[i]、TY[i],每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。
输出格式 Output Format
输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出?1。
样例输入 Sample Input
3 4 2
0 1 1 1
0 1 1 0
0 1 0 0
3 2 1 2 2 2
1 2 2 2 3 2
样例输出 Sample Output
2
-1
时间限制 Time Limitation
1s
注释 Hint
【输入输出样例说明】
棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。
1.   第一次游戏,空白格子的初始位置是 (3, 2)(图中空白所示),游戏的目标是将初始位置在(1, 2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2, 2)(图中红色的格子)上。
::点击图片在新窗口中打开::
2.   第二次游戏,空白格子的初始位置是(1, 2)(图中空白所示),游戏的目标是将初始位置在(2, 2)上的棋子(图中绿色圆圈所示)移动到目标位置 (3, 2)上。
::点击图片在新窗口中打开::
要将指定块移入目标位置,必须先将空白块移入目标位置,空白块要移动到目标位置,必然是从位置(2,2)上与当前图中目标位置上的棋子交换位置,之后能与空白块交换位置的只有当前图中目标位置上的那个棋子,因此目标棋子永远无法走到它的目标位置,游戏无法完成。
【数据范围】
对于 30%的数据,1 ≤ n, m ≤ 10,q = 1;
对于 60%的数据,1 ≤ n, m ≤ 30,q ≤ 10;
对于 100%的数据,1 ≤ n, m ≤ 30,q ≤ 500。
来源 Source
noip2013

题解

题目巨长,竟然还是华容道我没玩过,这道题不愧是noip2013最厉(bian)害(tai)的题,反正我看了半天一点思路都没有。。。。。。。。。。。。。。。
然后翻了一堆题解,彻底怀疑人生,noip出的这道题也太强(diu)大(liu)了吧,代码这么长。。。长到让我再次怀疑人生。。。。。。。。。。。。。。。。。。。。。。。。。。。。。连抄都不想抄,算了,还是好好写吧,先放一个大佬的讲解loi__frank,未来再好好研究这个题。。。。。。赶紧溜

代码

#include<bits/stdc++.h>
using namespace std;
const int N=35;
const int M=1e4+5;
const int dx[]={0,1,0,-1,0};
const int dy[]={0,0,1,0,-1};
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    return x*f;
}
struct node
{
    int x,y,k;
}l[M];
struct zt
{
    int x,y,step;
};
int n,m,mmp[N][N],f[N][N][5][5],d[N][N][5];
bool vis[N][N],inq[M];
int dist[M],tot=0,fan[]={0,3,4,1,2};
bool can(int x,int y)
{
    if (x>0 && x<=n && y>0 && y<=m && mmp[x][y]) return 1;
    return 0;
}
queue<zt>q1;
queue<int>q2;
void init()
{
    while (!q1.empty()) q1.pop();
    memset(vis,0,sizeof(vis));
}
int bfs1(int x,int y,int k,int h)
{
    init();
    vis[x][y]=1;
    int sx=x+dx[k],sy=y+dy[k];
    int tx=x+dx[h],ty=y+dy[h];
    q1.push((zt){sx,sy,0});
    while (!q1.empty())
    {
        zt F=q1.front();
        q1.pop();
        if (F.x==tx&&F.y==ty)
			return F.step;
        for (int i=1;i<=4;++i)
        {
            zt T;
            T.x=F.x+dx[i],T.y=F.y+dy[i];
            if (can(T.x,T.y) && !vis[T.x][T.y])
            {
                T.step=F.step+1;
                q1.push(T);
                vis[T.x][T.y]=1;
            }
        }
    }
    return -1;
}
void bfs2(int x,int y,int tx,int ty)
{
    init();
    vis[x][y]=1,vis[tx][ty]=1;
    q1.push((zt){x,y,0});
    while (!q1.empty())
    {
        zt F=q1.front();
        q1.pop();
        for (int i=1;i<=4;++i)
        {
            if (tx+dx[i]==F.x&&ty+dy[i]==F.y)
            {
                int dd=d[tx][ty][i];
                q2.push(dd);
                inq[dd]=1;
                dist[dd]=F.step;
                break;
            }
        }
        for (int i=1;i<=4;++i)
        {
            zt T;
            T.x=F.x+dx[i],T.y=F.y+dy[i];
            if (can(T.x,T.y) && !vis[T.x][T.y])
            {
                T.step=F.step+1;
                q1.push(T);
                vis[T.x][T.y]=1;
            }
        }
    }
}
void make_f()
{
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j)
            if (mmp[i][j])
                for (int k=1;k<=4;++k)
                    if (can(i+dx[k],j+dy[k]))
                        for (int h=1;h<=4;++h)
                            if (can(i+dx[h],j+dy[h]))
                            {
                                int w=bfs1(i,j,k,h);
                                if (w!=-1)
									f[i][j][k][h]=w;
                            }
}
void make_l()
{
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j)
            if (mmp[i][j])
                for (int k=1;k<=4;++k)
                {
                    d[i][j][k]=++tot;
                    l[tot].x=i,l[tot].y=j,l[tot].k=k;
                }
}
int spfa(int tx,int ty)
{
    while (!q2.empty())
    {
        int u=q2.front();
        q2.pop();
        inq[u]=0;
        int x=l[u].x,y=l[u].y,k=l[u].k;
        for (int i=1;i<=4;++i)
        {
            int zx=x+dx[i],zy=y+dy[i];
            if (can(zx,zy))
            {
                int v=d[zx][zy][fan[i]];
                if (dist[v]>dist[u]+f[x][y][k][i]+1)
                {
                    dist[v]=dist[u]+f[x][y][k][i]+1;
                    if (!inq[v]) q2.push(v),inq[v]=1;
                }
            }
        }
    }
    int ans=0x3fffffff;
    for (int i=1;i<=4;++i)
		ans=min(ans,dist[d[tx][ty][i]]);
    if (ans>1e9)
		ans=-1;
    return ans;
}
int main()
{
    n=read(),m=read();int p=read();
    memset(f,0x3f,sizeof(f));
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j)
            mmp[i][j]=read();
    make_f();
    make_l();
    while (p--)
    {
        int ex=read(),ey=read(),sx=read(),sy=read(),tx=read(),ty=read();
        memset(dist,0x3f,sizeof(dist));
        bfs2(ex,ey,sx,sy);
        if (sx==tx && sy==ty)
			puts("0");
        else
			printf("%d\n",spfa(tx,ty));
    }
    return 0;
}

标签:ch,noip2013,格子,int,题解,提高,位置,空白,棋子
来源: https://blog.csdn.net/huashuimu2003/article/details/84960614

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有