将Noip2010重新做了一遍,第一遍做下来居然只有290分,比当年浙江的一等线低了20分,因为各种坏习惯丢掉了许多分数,Noip时需要特别注意!

T1:机器翻译

  第一题直接暴力,内存足够所以不用循环队列,5分钟AC:

#include <cstdio>
int stack[10000],now;
int main(){int m,n;scanf("%d%d",&m,&n); int head=m;for(int i=0;i<m;i++)stack[i]=-1;for(int i=0;i<n;i++){bool flag=true;scanf("%d",&now);for(int j=head-m;j<head;j++)if(stack[j]==now){flag=false;break;}if(flag)stack[head++]=now;}printf("%d\n",head-m);return 0;
}

T2:乌龟棋

  对于这道题目直接以四种卡片为状态进行四维Dp就可以了,注意DP时加上的是格子1*i+2*j+3*k+4*l的数值,而不是i+j+k+l的,一开始出错调试时都过不了,修改好AC:

#include <cstdio>
int t[5],a[40000],s[5];
int f[41][41][41][41];
int main(){int m,n,in,ans=0;scanf("%d%d",&n,&m);for(int i=0;i<n;i++)scanf("%d",&a[i]);for(int i=0;i<m;i++)scanf("%d",&in),s[in]++;f[0][0][0][0]=a[0];for(int i=0;i<=s[1];i++)for(int j=0;j<=s[2];j++)for(int k=0;k<=s[3];k++)for(int l=0;l<=s[4];l++){if(f[i+1][j][k][l]<f[i][j][k][l]+a[1*i+2*j+3*k+4*l+1])f[i+1][j][k][l]=f[i][j][k][l]+a[1*i+2*j+3*k+4*l+1];if(f[i][j+1][k][l]<f[i][j][k][l]+a[1*i+2*j+3*k+4*l+2])f[i][j+1][k][l]=f[i][j][k][l]+a[1*i+2*j+3*k+4*l+2];if(f[i][j][k+1][l]<f[i][j][k][l]+a[1*i+2*j+3*k+4*l+3])f[i][j][k+1][l]=f[i][j][k][l]+a[1*i+2*j+3*k+4*l+3];if(f[i][j][k][l+1]<f[i][j][k][l]+a[1*i+2*j+3*k+4*l+4])f[i][j][k][l+1]=f[i][j][k][l]+a[1*i+2*j+3*k+4*l+4];}for(int i=0;i<=s[1];i++)for(int j=0;j<=s[2];j++)for(int k=0;k<=s[3];k++)for(int l=0;l<=s[4];l++){if(f[i][j][k][l]>ans&&(i+2*j+3*k+4*l+1==n))ans=f[i][j][k][l];}printf("%d\n",ans);return 0;
}

T3:关押罪犯

  属于最大值最小问题,可以用二分答案,BFS检验一下,但是我直接用的是并查集,感觉就是先排序,然后按边权由大到小进行并查集,关在同一个地方的建1边,关在不同地方的建0边,当然,对于数据全都建1边,在传递时01交替即可,一开始因为懒,没有码余数体系,直接敲了异或,没考虑全面,只拿了六十分,后来还是老老实实地写了下余数体系,AC~

#include <cstdio>
#include <algorithm>
using namespace std;
int f[20005],r[20005];
struct seg{int a,b,l;friend bool operator <(const seg&a,const seg&b){return a.l>b.l;}
}s[100005];
int sf(int x){if (f[x]==x) return x;int fx=sf(f[x]);r[x]=(r[x]+r[f[x]])%2;return f[x]=fx;
}
void Union(int x,int y,int fx,int fy,int d)
{f[fy]=fx;r[fy]=(2-r[y]+d+r[x])%2;
}
int main(){int m,n;scanf("%d%d",&n,&m);for(int i=0;i<m;i++)scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].l);sort(s,s+m);for(int i=1;i<=n;i++)f[i]=i;for(int i=0;i<m;i++){int fa=sf(s[i].a),fb=sf(s[i].b);if(fa==fb){if(r[s[i].a]==r[s[i].b]){printf("%d",s[i].l);return 0;}}else Union(s[i].a,s[i].b,fa,fb,1);}puts("0");return 0;
}

T4:引水入城

  最后一题题目还是不错的,可惜推出了大半的结论,却因为代码的原因只拿了30分,特别反省一下,首先看到题目,想到floodfill,对于第一排的每一个点可以进行一次种子填充法,然后就可以知道能够填到的地方,但是这样子复杂度过高,那么是不是所有的点都要填一遍呢?

  观察上面这张图,我们可以发现,如果第一排要填充的点比周围的点低,那么在填充那个点的时候就可以直接填到这个点,即一定比填充此点要优,所以在填充时,只需要填比两边点都要大或相等的点,即上图中的8,6,4,那么填充之后得到的数据该怎么处理呢?

  对于每次填充其实都生成了一条线段,注意线段计算时只取第一段连续的可灌溉点,如果是不连续的,必然无解,因为水断点如果可以被另一条线段覆盖,则一定比当前优,因为其必然可以灌溉到当前线段所能灌到的所有点。

  最后是求最少线段覆盖的典型贪心问题了,一开始我以为O(n)可以解决,结果发现是错的,每次取有交集的最长线段必须要扫一遍才可以,否则不一定是最优的,贴上错误代码,警示一下!

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int map[505][505],m,n;
int b[505][505];
struct seg{int a,b;}s[505];
bool cmp(seg x,seg y){if(x.a==y.a)return x.b>y.b;return x.a<y.a;
}
void floodfill(int x,int y){b[x][y]=1;if(x+1<=n&&map[x+1][y]<map[x][y]&&!b[x+1][y])floodfill(x+1,y); if(x-1>0&&map[x-1][y]<map[x][y]&&!b[x-1][y])floodfill(x-1,y);if(y+1<=m&&map[x][y+1]<map[x][y]&&!b[x][y+1])floodfill(x,y+1);if(y-1>0&&map[x][y-1]<map[x][y]&&!b[x][y-1])floodfill(x,y-1);
}
int main(){freopen("flow.in","r",stdin);freopen("flow.out","w",stdout);int i,j,top=0;scanf("%d%d",&n,&m);for(i=1;i<=n;i++)for(j=1;j<=m;j++)scanf("%d",&map[i][j]);for(i=1;i<=m;i++)if(map[1][i]>=map[1][i+1]&&map[1][i]>=map[1][i-1]){memset(b,0,sizeof b);floodfill(1,i);for(j=1;j<=m;j++)if(b[n][j]){s[top].a=j;break;}if(s[top].a==0)continue;for(j=s[top].a;;j++)if(!b[n][j]){s[top++].b=j-1;break;}}sort(s,s+top,cmp);int l=s[0].a,r=s[0].b,tmp=1;for(j=1;j<top;j++)if((s[j].a-1)<=r&&s[j].b>r){r=s[j].b;tmp++;}if(r==m&&l==1){puts("1");printf("%d\n",tmp);}else{int tmp=0; for(i=1;i<=m;i++)if(map[1][i]>=map[1][i+1]&&map[1][i]>=map[1][i-1])floodfill(1,i);for(j=1;j<=m;j++)if(!b[n][j])tmp++;puts("0");printf("%d\n",tmp); }return 0;fclose(stdin);fclose(stdout);
}

然后是AC程序

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int map[505][505],m,n;
int b[505][505];
struct seg{int a,b;}s[505];
bool cmp(seg x,seg y){if(x.a==y.a)return x.b>y.b;return x.a<y.a;
}
void floodfill(int x,int y){b[x][y]=1;if(x+1<=n&&map[x+1][y]<map[x][y]&&!b[x+1][y])floodfill(x+1,y); if(x-1>0&&map[x-1][y]<map[x][y]&&!b[x-1][y])floodfill(x-1,y);if(y+1<=m&&map[x][y+1]<map[x][y]&&!b[x][y+1])floodfill(x,y+1);if(y-1>0&&map[x][y-1]<map[x][y]&&!b[x][y-1])floodfill(x,y-1);
}
int main(){int i,j,top=0;scanf("%d%d",&n,&m);for(i=1;i<=n;i++)for(j=1;j<=m;j++)scanf("%d",&map[i][j]);for(i=1;i<=m;i++)if(map[1][i]>=map[1][i+1]&&map[1][i]>=map[1][i-1]){memset(b,0,sizeof b);floodfill(1,i);for(j=1;j<=m;j++)if(b[n][j]){s[top].a=j;break;}if(s[top].a==0)continue;for(j=s[top].a;;j++)if(!b[n][j]){s[top++].b=j-1;break;}}sort(s,s+top,cmp);int l=1,r=0,tmp=0; bool flag;do{int max=0; flag=1; for(int i=0;i<top;i++)if(s[i].a-1<=r&&s[i].b>r){if(s[i].b>max)max=s[i].b;flag=0;}r=max; tmp++;}while(r!=m&&!flag);if(r==m){puts("1");printf("%d\n",tmp);}else{int tmp=0; for(i=1;i<=m;i++)if(map[1][i]>=map[1][i+1]&&map[1][i]>=map[1][i-1])floodfill(1,i);for(j=1;j<=m;j++)if(!b[n][j])tmp++;puts("0");printf("%d\n",tmp); }return 0;
}

 注意点:

  1.不要忘记return 0;

  2.提交时while(1)记得要去掉!!!

  3.注意Noip时一定要开cstring,iostream不可以代替cstring!

  4.注意判断用双等号! 白丢70分的教训啊~

  5.加权并查集不可以用异或,100降为60分得出的结论

  6.一定要多造数据来检测自己的程序!

转载于:https://www.cnblogs.com/forever97/p/Noip2010.html

Noip2010提高组总结相关推荐

  1. NOIP2010 提高组 复赛 translate 机器翻译

    NOIP2010 提高组 复赛 translate 机器翻译 1.读题,很快弄明题意,单词不在内存中就查字典,统计查字典次数. 2.内存采用队列方式.统计进队列次数,即为查询次数. 3.程序很快编好, ...

  2. #洛谷oj:P1525 [NOIP2010 提高组] 关押罪犯

    洛谷oj:P1525 [NOIP2010 提高组] 关押罪犯 #题目描述 #一看很明显是贪心算法 加排序 因为 这个中间最大值的那一对肯定是不会在一起的 从大到小来看 所有点对都尽量不要在一个监狱 # ...

  3. NOIP2010提高组题解

    [NOIP2010 提高组] 机器翻译 题目:[NOIP2010 提高组] 机器翻译 题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单 ...

  4. 凡人升天传7——NOIP2010 提高组复赛题解

    本蒟蒻在考试时最后一道直接报零*__*,悲痛欲绝,因此在这里著下本题解. 可恶的西西弗 虽然题目做的很垃圾,但在写题解中途不得不感叹除了最后一道,其他真是好水题呀!!! --------------- ...

  5. noip2010提高组3题题解 by rLq

    本题地址http://www.luogu.org/problem/show?pid=1525 关押罪犯 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和 ...

  6. [NOIP2010提高组]关押罪犯

    题目:洛谷P1525.Vijos P1776.codevs1069. 题目大意:有一些罪犯,两个罪犯之间可能会发生冲突,冲突有个影响力,而如果两个罪犯在不同监狱里,就可以避免冲突.现在有两个监狱,要你 ...

  7. NOIP2010 提高组 机器翻译

    题目:http://www.tsinsen.com/ViewGProblem.page?gpid=A1182 解析:题目比较简单,应用了对列(数组模拟) 评测: /** =============== ...

  8. NOIP2010提高组初赛 c++————烽火传递

    题目描述 烽火台是重要的军事防御设施,一般建在交通要道或险要处.一旦有军情发生,则白天用浓烟,晚上有火光传递军情. 在某两个城市之间有 n 座烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确传 ...

  9. NOIP2010提高组 关押罪犯

    题目链接 题意就是,把罪犯放到两个不同的监狱中,每个犯人之间可能会有冲突值,如果两个犯人分在同一个监狱内他们的冲突值就会被激活,产生影响力为冲突值的冲突,监狱内的冲突值为所有人之间冲突的最大值,求分配 ...

  10. NOIP1998-2018 CSP-S2 2019 2021提高组解题报告与视频

    CSP-S 2020 讲题录屏 CSP-S 2020 讲题录屏_哔哩哔哩_bilibili 冠军说题--ACM世界冠军吴卓杰,带你复盘2020 CSP-S2 冠军说题--ACM世界冠军吴卓杰,带你复盘 ...

最新文章

  1. JQuery元素选择器:和||,逻辑选择
  2. 致青春VS杜蕾斯,用QQ空间电影大数据解读关联性
  3. 【模板】第二类斯特林数Stirling
  4. Java Hessian小试(转)
  5. 微软Visual Studio 2005快捷键文档
  6. 给字符串对象定义一个repeat功能。当传入一个整数n时,它会返回重复n次字符串的结果。
  7. 提高篇 第一部分 基础算法 第4章 广搜的优化技巧
  8. 谈谈如何在面试中发掘程序猿的核心竞争力 什么是程序员的核心竞争力?
  9. python3x完全兼容python2x_李亚涛:一台电脑python2x与python3x如何都可以用?
  10. matlab中输入x. 与x的区别
  11. 学会5个数据分析常见定律,数据敏感度提升N个度
  12. 计算机学office有必要吗,计算机二级office要学多久
  13. Github上不错的Android开源代码(一)
  14. http code 000
  15. 银行软开开发篇[转]
  16. 短视频解析去水印在线 伪原创视频如何搬运
  17. python爬取凤凰新闻_python爬虫凤凰网新闻
  18. 只有1kb的清理软件_1kb病毒专杀工具下载
  19. 从猎豹到山狮-苹果操作系统热衷于猫科动物代号
  20. Windows10 64位企业版 1909真机中使Wireshark可以抓取802.1q封装携带tag的数据帧

热门文章

  1. markdown格式的文章如何转换为可以发布在微信公众号上的内容
  2. 宝塔apache mysql_宝塔Linux面板命令大全,安装宝塔,Nginx,Apache,MySQL等 - SEO中文网...
  3. python怎么计算圆上任意两点的距离_圆周上两点距离-python
  4. 定制MyBatis的日志
  5. Spring源码之bean的加载(二)获取单例bean
  6. (转)EOSIO开发(四)- nodeos、keosd与cleos
  7. linq group by 多个字段取值以及取出重复的数据
  8. C++第八周学习小结
  9. 安装篇——nginx安装ssl模块转发https请求
  10. 进程占用导致linux中命令无法执行