NOIP2010题解
来源:互联网 发布:linux java 打包jar 编辑:程序博客网 时间:2024/06/14 02:42
所有题目链接均来自洛谷
T1机器翻译
原题戳这里
自古T1是水题
因为每一个数字都小于1000,所以对于是否在队列中可以开数组查询
对于大小的限制,弄一个队列维护大小即可(水题呀。。。) 这题在Windows下写的,不要在意缩进
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<algorithm>using namespace std;int ans=0,m,n,a,len=0;queue<int> Q;int vis[1001];int main(){ cin>>m>>n; for(int i=1;i<=n;++i) { cin>>a; if(!vis[a]) { if(len<m) { vis[a]=true; ++ans; Q.push(a); ++len; } else { vis[a]=true; ++ans; vis[Q.front()]=false; Q.pop(); Q.push(a); } } } cout<<ans<<endl; return 0;}
T2乌龟棋
题面戳我
很容易想到DP
很容易可以想到设f[i][j][k][l][m]表示当前走到第i格,对于每张牌分别用了j,k,l,m张
但是这样子很显然会炸空间
继续考虑,如果已经知道每张卡用了多少张,实际上就可以直接计算出当前走到了哪一格,因此第一维可以省去,然后就是一个比较容易的四维DP了
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>using namespace std;inline int read(){ register int x=0,t=1; register char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'){t=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*t;}//f[x][y][z][w]表示//1步的卡片用x张,2步的卡片用y张//3步的卡片用z张,4步的卡片用w张//的时候,能够拿到最大的分数 int f[41][41][41][41];int n,m;int A[500],B[5];int main(){ n=read(); m=read(); for(int i=1;i<=n;++i) A[i]=read(); for(int i=1;i<=m;++i) B[read()]++; f[0][0][0][0]=A[1];//赋初值 for(int i=0;i<=B[1];++i) for(int j=0;j<=B[2];++j) for(int k=0;k<=B[3];++k) for(int l=0;l<=B[4];++l) { int d=A[i+j+j+k+k+k+l+l+l+l+1]; if(i!=0) f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+d); if(j!=0) f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]+d); if(k!=0) f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]+d); if(l!=0) f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]+d); } cout<<f[B[1]][B[2]][B[3]][B[4]]<<endl; return 0; }
T3关押罪犯
题目在这里
这题有难度了,当时我就搞了好久才弄懂。。。。
如果只说,这道题恐怕也很难说清楚,那么我就尽可能的说清楚。
首先考虑的的是影响力最小,
那么我们就贪心的尽可能解决影响力最大的事件
既然要将人分成两组,那么所有人其实也可以归类为两个集合
一组是和某个人在一个监狱的集合,
另一组是和某个人不在某一个监狱的集合。
现在要考虑的就是解决集合,那么使用并查集
每次解决一组冲突的方法就是将两个人放到不同的监狱,
即将某个人放到另一个人不在一个监狱的集合里面。
如果当前这两个人已经在一个集合中了,那么当前的影响力就是答案,直接输出即可。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define MAX 20010#define MAXL 100010using namespace std;struct Line{ int x,y,w;}e[MAXL];int n,m,f[MAX];int be[MAX];inline int getf(int x){ return x==f[x]?x:f[x]=getf(f[x]);}bool operator <(Line a,Line b){ return a.w>b.w;}int main(){ cin>>n>>m; for(int i=1;i<=n*2;++i) f[i]=i; for(int i=1;i<=m;++i) cin>>e[i].x>>e[i].y>>e[i].w; sort(&e[1],&e[m+1]); for(int i=1;i<=m;++i) { int u=getf(e[i].x); int v=getf(e[i].y); if(u==v)//如果在同一个监狱里 { cout<<e[i].w<<endl;//不可避免的是最大值 return 0; } else { f[v]=getf(e[i].x+n); f[u]=getf(e[i].y+n); } } cout<<0<<endl; return 0;}
T4引水入城
题面。。。
这道题目拆开讲觉得好简单呀,但是组合在一起觉得有些麻烦了。。。。
首先我们要证明一下如果数据有解的话,每一个地方建造蓄水场,那么它可以影响的旱区的城市一定是一段连续的区间。
既然有解,证明每一个旱区的城市都可以被影响到,
利用反证法,假设存在一个地方供水区间分为两段,中间有一个城市不能够被当前位置影响到。 还是画图吧。。。
也就是这样子
但是中间这个玩意能够被其他的地方覆盖到,也就是这样。
那么这个可以覆盖到的那个蓄水站必然能够影响到左侧的位置
但是它要影响左侧的位置,它的水的覆盖就穿过了原来的那个供水站的影响位置
那么证明当前的供水站其实也是可以覆盖到中间的那个位置的。
如果我还没有讲清楚请画图吧。。。
好了,
现在简单了,对于第一问,直接DFS或者BFS直接覆盖一下位置,检查能否覆盖到所有的干旱地区。
如果可以覆盖的话,上方每一个蓄水站的覆盖区域就是一个线段,
那么可以贪心的求最少的覆盖数。
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int MAX=501;int d[4][2]={1,0,-1,0,0,-1,0,1};bool map[MAX][MAX];bool book[MAX];int m,n,g[MAX][MAX];int L[MAX],R[MAX];int f[MAX];struct dsl{ int L; int R;}syc[MAX];bool cmp(dsl a,dsl b){ if(a.L<b.L)return true; else return false;}void DFS(int x,int y){ int x1,y1; for(int i=0;i<4;++i) { x1=x+d[i][0]; y1=y+d[i][1]; if(x1>n||x1<=0||y1>m||y1<=0||g[x1][y1]>=g[x][y])continue; if(map[x1][y1])continue; map[x1][y1]=true; DFS(x1,y1); }}int main(){ cin>>n>>m; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) cin>>g[i][j]; int l,r; for(int i=1;i<=m;++i) { l=MAX;r=0; memset(map,0,sizeof(map)); map[1][i]=true; DFS(1,i); for(int j=1;j<=m;++j) if(map[n][j]) { book[j]=true; if(!map[n][j-1]&&map[n][j])l=j; if(!map[n][j+1]&&map[n][j])r=j; } syc[i].L=l; syc[i].R=r; } int count=0; bool fl=true; for(int i=1;i<=m;++i) { if(!book[i]) fl=false,++count; } if(!fl) { cout<<0<<endl<<count<<endl; return 0; } else { memset(f,127,sizeof(f)); f[0]=0; sort(&syc[1],&syc[m+1],cmp); for(int i=1;i<=m;++i) for(int j=syc[i].L;j<=syc[i].R;++j) { f[j]=min(f[syc[i].L-1]+1,f[j]); } cout<<1<<endl; cout<<f[m]<<endl; } return 0;}
- NOIP2010题解
- 【NOIP2010】乌龟棋题解
- NOIP2010 机器翻译 题解
- NOIP2010普及组题解
- NOIP2010引水入城题解
- NOIP2010普及组题解 -SilverN
- 【NOIP2010】【模拟】T1 机器翻译 题解
- [NOIP2010]三国游戏 T4 题解
- 【NOIP2010】【DP】T2 乌龟棋 题解
- NOIp2010
- NOIP2010
- noip2010提高组3题题解 by rLq
- 【NOIP2010】【并查集】T3 关押罪犯 题解
- 【NOIP2010】【贪心】【覆盖问题】T4 引水入城 题解
- 【NOIP2010初赛】【斜率优化】【DP】烽火传递 题解
- NOIP2010 普及组 蒟蒻的题解报告
- 【蒻爆了的NOIP系列--普及组复赛】(1)NOIP2010普及组复赛题解
- NOIP2010第一道 ---导弹拦截(摘自洛谷题解)
- codeforce 850A Five Dimensional Points(特殊判别)
- OJ 2523: 建房工程
- log4j输出多个自定义日志文件,动态配置路径
- ImageLoader
- Head First Java 总结(一)
- NOIP2010题解
- Git的基本使用-常用命令速查表
- V5.0 Cas Server及子系统全部退出
- Send函数和Recv函数解析
- spring boot打包 部署 依赖 hc/info
- 【Qt】Qt Creator中文输入设置
- springboot 构建微服务设置远程调试
- bzoj4720: [Noip2016]换教室
- BIEE 11g DB认证用户密码加密问题