NOIP2010解题报告
来源:互联网 发布:一搜网络 编辑:程序博客网 时间:2024/05/22 16:20
题目链接:
T1 机器翻译
T2 乌龟棋
T3 关押罪犯
T4 引水入城
题解:
一套不算太难的NOIP题目。
第一题直接暴力模拟队列的工作即可。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>using namespace std;int q[10100];int in(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}int main(){ int m=in(),n=in(); int h=1,t=1,s=0; for (int i=1; i<=n; i++){ int x=in(); bool f=false; for (int j=h; j<t; j++) if (q[j]==x){ f=true; break; } if (!f){ s++,q[t++]=x; if (t-h>m) h++; } } printf("%d\n",s); return 0;}
第二题我写的是
f[i][j][k][l]表示当前用了i张1步的,j张2步,k张3步,l张4步。
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<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>using namespace std;int f[50][50][50][50]={0},a[400],b[6];int in(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}int main(){ int n=in(),m=in(); for (int i=1; i<=n; i++) a[i]=in(); for (int i=1; i<=m; i++) b[in()]++; 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 s=0; if (i) s=max(s,f[i-1][j][k][l]); if (j) s=max(s,f[i][j-1][k][l]); if (k) s=max(s,f[i][j][k-1][l]); if (l) s=max(s,f[i][j][k][l-1]); f[i][j][k][l]=a[i+j*2+k*3+l*4+1]+s; } printf("%d\n",f[b[1]][b[2]][b[3]][b[4]]); return 0;}
第三题并查集,把所有的冲突按照值从大到小排序,然后每一个冲突的两端加进两个不同的集合,直到出现冲突,此时这个冲突的值就是我们最终分配完后出现的最大的那个冲突值,输出即可,如一直没有冲突,就输出0了。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>using namespace std;struct S{ int x,y,c;}a[100010];int n,nn,m,fa[40010];int in(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}bool cmp(S a,S b){ return a.c>b.c;}int find(int x){ return fa[x]!=x?fa[x]=find(fa[x]):x;}int main(){ n=in(),m=in(); nn=n<<1; for (int i=1; i<=nn; i++) fa[i]=i; for (int i=1; i<=m; i++) a[i].x=in(),a[i].y=in(),a[i].c=in(); sort(a+1,a+m+1,cmp); for (int i=1; i<=m; i++){ int f1=find(a[i].x),f2=find(a[i].y); if (f1!=f2) fa[f1]=find(a[i].y+n),fa[f2]=find(a[i].x+n); else { printf("%d\n",a[i].c); return 0; } } printf("0\n"); return 0;}
第四题开始想到了正常解法,后来脑抽想去搞一个最短路(来源于费用流的启发)。。于是颓了很久,后来还是写了正常的做法。。写完后去看了一下题解,发现好像真的可以跑最短路(囧。。)
说一下正常做法:
首先把第一行入队,bfs一遍,看最后一行是否全都能访问到,不能就直接输出0和不能访问的个数,否则就重新对于第一行的每个点dfs(bfs一样。。懒的写两遍了。。)一遍,然后统计一下它能访问到的最后一行的区间(这个一定是连续的,可以证明。。但我是脑补出来的。。),然后就是经典线段覆盖的dp了。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define N 1001000#define M 600struct Q{ int x,y;}q[N];struct E{ int l,r;}e[M];int dx[6]={0,0,-1,1},dy[6]={-1,1,0,0};int n,m,f[M],a[M][M]; bool vis[M][M];int in(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}void bfs(){ memset(vis,0,sizeof(vis)); int h=0,t=1; for (int i=1; i<=m; i++){ q[t++]=(Q){1,i}; vis[1][i]=true; } while (h<t){ Q u=q[h++]; for (int i=0; i<4; i++){ Q v; v.x=u.x+dx[i],v.y=u.y+dy[i]; if (vis[v.x][v.y] || v.x<1 || v.x>n || v.y<1 || v.y>m) continue; if (a[u.x][u.y]>a[v.x][v.y]) q[t++]=v,vis[v.x][v.y]=true; } }}void init(){ bfs(); int s=0; for (int i=1; i<=m; i++) if (!vis[n][i]) s++; if (!s) printf("1\n"); else { printf("0\n%d\n",s); exit(0); }}void dfs(int xu,int x,int y){ vis[x][y]=true; if (x==n){ e[xu].l=min(e[xu].l,y); e[xu].r=max(e[xu].r,y); } for (int i=0; i<4; i++){ int xx=x+dx[i],yy=y+dy[i]; if (vis[xx][yy] || xx<1 || xx>n || yy<1 || yy>m) continue; if (a[x][y]>a[xx][yy]) dfs(xu,xx,yy); }}void dp(){ memset(f,0x3f,sizeof(f)); f[0]=0; for (int i=1; i<=m; i++){ for (int j=1; j<=m; j++) if (i>=e[j].l && i<=e[j].r) f[i]=min(f[i],f[e[j].l-1]+1); }}int main(){ n=in(),m=in(); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) a[i][j]=in(); init(); for (int i=1; i<=m; i++){ memset(vis,0,sizeof(vis)); e[i].l=m+1,e[i].r=0; dfs(i,1,i); } dp(); printf("%d\n",f[m]); return 0;}
0 0
- NOIP2010解题报告
- [NOIP2010] 乌龟棋 解题报告
- [NOIP2010] 关押罪犯-解题报告
- NOIP2010提高组 关押罪犯 解题报告
- NOIP2010 机器翻译 解题报告(水题)
- 【算法】NOIP2010提高组解题报告
- NOIP2010 乌龟棋 解题报告(4维DP)
- NOIP2010 引水入城 解题报告(bfs+dp)
- 全国信息学奥林匹克联赛(NOIP2010)复赛 1.数字统计 解题报告
- 全国信息学奥林匹克联赛(NOIP2010)复赛 2.接水问题 解题报告
- 全国信息学奥林匹克联赛(NOIP2010)复赛 3.导弹拦截 解题报告
- NOIP2010 关押罪犯 解题报告(并查集,补集判断思想)
- NOIP2010普及组 导弹拦截(重庆一中高2018级信息学竞赛测验3) 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- tcp的Nagle算法
- 数组
- 对象(2)
- 在线考试系统——测试计划 详细测试报告——testlink
- java 第十天 面向对象
- NOIP2010解题报告
- JavaScript学习笔记7-附录(回掉函数)
- 对数组的操作
- wxpython初学者(三)
- hdu 1500 Chopsticks(动态规划)
- okio分析
- Java版本的一些问题
- 编写SQL查询,列出租住不止一套公寓的承租人
- 内省和BeanUtils框架3