2017暑假第二阶段第一场 总结
来源:互联网 发布:wear软件安装不了 编辑:程序博客网 时间:2024/05/19 20:42
T1 数三角形
问题描述
给出一个正整数n,从1,2,3…..n 中选出三个不同整数,使得以它们为三边长可以组成三角形,问
总共有多少种不同的三角形?
例如,n=5 时有三种:(2,3,4) , (2,4,5) , (3,4,5)
输入格式
一个正整数n
输出格式
一个整数,表示三角形的个数
递推即可。
设f[i]表示n为i时的方案总数,那么f[i+1]相比f[i],多出的方案为最长边为i的三角形个数。分奇偶性不难推导。
#include<iostream>using namespace std;long long Ans,i,N;int main(){ cin>>N; for(i=4;i<=N;i++) { if(i&1)Ans+=(i-3)*(i-1)/4; else Ans+=(i-2)*(i-2)/4; } cout<<Ans;}
T2 翻硬币
问题描述
两个玩家在玩一个有趣的翻硬币游戏。
有 N 枚硬币排成一排,有的正面朝上,有的反面朝上。从左往右硬币按1 到N 编号。玩家轮流操作。每次操作,玩家选一枚正面朝上的硬币,将它翻转,同时在该硬币左侧连续四个硬币中,再任选一个硬币,将其翻转。
具体而言,假设第i号硬币正面朝上。若将第i号硬币翻转后,必须在编号为i-1,i-2,i-3,i-4的四个硬币中选一个进行翻转。若i<=4,则可只翻转i号硬币,也可以再在1到i-1之间选一个进行翻转。谁没有硬币可翻谁就算输。两个玩家都非常聪明,问先手是否获胜?
输入格式
第一行,一个正整数T,表示接下来有T组测试数据。对于每组测试数据:
第1行,一个整数N,表示硬币的数量。
第2行,N个空格间隔的整数(0和1),从左往右依次表示游戏开始前硬币的情况,其中数字0表示正面朝下,数字1表示正面朝上。
输出格式
T行,每行对应一组测试数据的答案。若先手胜输出”Yes” 否则输出“No”
将0,1,01,001,0001,……的SG值计算出后,显然可以用其中某些值的异或和表示任意状态。
容易发现规律,在上面的数列中,当1为从左往右第i个数时,SG值为i%5。
#include<stdio.h>int T,N;int main(){ int i,x,SG; scanf("%d",&T); while(T--) { SG=0; scanf("%d",&N); for(i=1;i<=N;i++) { scanf("%d",&x); if(x)SG^=i%5; } if(SG)puts("Yes"); else puts("No"); }}
T3 小鸟
问题描述
有一排n棵树,第i棵树的高度是Di。 一群小鸟要从第1棵树飞到第n棵树去玩。
不同小鸟的飞跃能力不同,第i只小鸟的飞跃能力为ki,表示如果当前它位于第x号树,那么它可以飞到x+1,x+2,……,x+ki号树上去,也就是一次可以飞过ki棵树。
如果小鸟飞到一棵不矮于当前树的树,那么他的劳累值会+1,否则不会。 小鸟们希望最小化劳累值,请你计算每只小鸟达到终点所需最小劳累值。
输入格式
第一行,一个整数N(2<=N<=100000)
第二行,N个空格间隔的整数,第i个数表示第i棵树的高度Di。(1<=Di<=10^9)
第三行,一个整数Q(1<=Q<=25),表示小鸟的数量
接下来Q行,每行一个整数,其中第i个整数表示第i只小鸟的飞跃能力ki。
输出格式
Q行,每行一个整数,表示对应小鸟的劳累值
单调队列优化DP。
设f[i]表示小鸟飞到第i棵树时的最小劳累值,很容易写出状态转移方程。时间复杂度为O(Nk)。可以用单调队列优化为O(N)的级别。
根据题目要求,维护一个单调递增的队列。当f的值相等时,D较大的更优。
#include<stdio.h>#include<deque>#define MAXN 100005using namespace std;int D[MAXN],N,Q,K,f[MAXN];int main(){ int i,k; deque<int>S; scanf("%d",&N); for(i=1;i<=N;i++)scanf("%d",&D[i]); scanf("%d",&Q); for(k=1;k<=Q;k++) { f[1]=0; while(S.size())S.pop_back(); S.push_back(1); scanf("%d",&K); for(i=2;i<=N;i++) { if(S.front()<i-K)S.pop_front(); f[i]=f[S.front()]; f[i]+=D[i]>=D[S.front()]; while(S.size()&&(f[S.back()]>f[i]||(f[S.back()]==f[i]&&D[S.back()]<=D[i])))S.pop_back(); S.push_back(i); } printf("%d\n",f[N]); }}
T4 乘车路线
问题描述
编号为 1.. N的N座城镇用若干仅供单向行驶的道路相连,每条道路上均有两个参数:道路长度(length)和在该条道路上行驶的费用(cost)。
BOB准备从城镇 1 出发到达城镇 N,但他目前只有 W 块钱,为此,你需要帮助他寻找一条从城镇1到城镇 N 在他能支付的前提下的一条最短路线。
输入格式
第一行为钱的数目W (0<=w<=1000)
第二行为城镇数目N(2<=N<=100)
第三行为为道路条数K(1<=K<=10000)
随后的 K 行每行为一条道路的信息,包含 4个数值(S,D,L,T)其中S为道路的起点, D为道路的终点 , L为道路长度, T为所需支付费用。 (1<=S,D<=N,1<=L<=100,0<=T<=100)
输出格式
输出最短长度,若无解,则输出“NO”
乍一眼可能觉得是网络流,但是并不是。
方法一:
由于数据规模不大,记忆化搜索加上其他一些剪枝可以跑得飞快,甚至优于方法二。
m[i][j]表示走到i号点,费用为i的最小时间。
#include<stdio.h>#include<cstring>const int MAXN=105,MAXM=10005,inf=1e9;int W,N,K,Ans=inf;int m[105][1005];int tot,en[MAXM],las[MAXN],nex[MAXM],len[MAXM],cos[MAXM];void ADD(int x,int y,int l,int t){ en[++tot]=y; nex[tot]=las[x]; las[x]=tot; len[tot]=l; cos[tot]=t;}void DFS(int x,int t,int c){ int i,y; if(t>Ans)return;//最优化剪枝 if(c>W)return;//可行性剪枝 if(m[x][c]<t)return;//记忆化 m[x][c]=t; if(x==N) { if(Ans>t)Ans=t; return; } for(i=las[x];i;i=nex[i])y=en[i],DFS(y,t+len[i],c+cos[i]);}int main(){ int i,x,y,l,t; memset(m,60,sizeof(m)); m[1][0]=0; scanf("%d%d%d",&W,&N,&K); for(i=1;i<=K;i++)scanf("%d%d%d%d",&x,&y,&l,&t),ADD(x,y,l,t); DFS(1,0,0); if(Ans==1e9)puts("NO"); else printf("%d",Ans);}
方法二
设dis[i][j]表示走到i号点,且花费为j时的最短距离。那么对SPFA稍加改动即可。
#include<stdio.h>#include<queue>#include<cstring>using namespace std;const int MAXN=105,MAXM=10005;int Ans=1e9;int W,N,K;int tot,en[MAXM],las[MAXN],nex[MAXM],len[MAXM],cos[MAXM];void ADD(int x,int y,int l,int t){ en[++tot]=y; nex[tot]=las[x]; las[x]=tot; len[tot]=l; cos[tot]=t;}bool mark[MAXN];int dis[105][1005];void SPFA(){ queue<int>Q; memset(dis,60,sizeof(dis)); int i,j,x,y; for(i=0;i<=W;i++)dis[1][i]=0; Q.push(1); while(Q.size()) { x=Q.front();Q.pop();mark[x]=false; for(i=las[x];i;i=nex[i]) { y=en[i]; for(j=cos[i];j<=W;j++) { if(dis[y][j]>dis[x][j-cos[i]]+len[i]) { dis[y][j]=dis[x][j-cos[i]]+len[i]; if(!mark[y])mark[y]=true,Q.push(y); } } } }}int main(){ int i,x,y,l,t; scanf("%d%d%d",&W,&N,&K); for(i=1;i<=K;i++) { scanf("%d%d%d%d",&x,&y,&l,&t); ADD(x,y,l,t); } SPFA(); for(i=0;i<=W;i++)Ans=Ans>dis[N][i]?dis[N][i]:Ans; if(Ans>=dis[0][0])puts("NO"); else printf("%d",Ans);}
总结
本次比赛题目总体难度不难。T1静下心来很容易就能AC;T2主要考查博弈的结论;T3是数据结构单调队列比较裸的题;T4由于数据范围不大,应该想到可以采用比较暴力的做法。
优点主要是T1、T2做得较快;T3、T4虽然没能AC,但第一感觉就是正解。
缺点主要暴露在:对学过的某些数据结构不够熟悉,否则能够AC掉T3,也不会浪费掉太多时间;不敢在T4的位置写搜索,在实在没想到更优的解法时也应该尽量把优化后的搜索写下来。
- 2017暑假第二阶段第一场 总结
- 2017暑假第二阶段第二场 总结
- 2017暑假第二阶段第三场 总结
- 2017暑假第二阶段第四场 总结
- 2017暑假第二阶段第五场 总结
- 2017暑假第二阶段第六场 总结
- 2017暑假第二阶段第七场 总结
- 2017暑假第二阶段第八场 总结
- 2017暑假第二阶段第九场 总结
- 暑假第一场A。Eming
- 暑假第一场D.Brackets
- 暑假第一场E。Function
- 2017暑假训练第一场的一些题目
- 2017ACM暑假俱乐部第一场H题 wtaxi
- 新生赛暑假第一场 解题报告
- 暑假第一场B。Arithmetic Progression
- 暑假集训-个人赛第一场
- 17暑假多校第一场B
- web——CSS中position属性( absolute 、 relative 、static 、 fixed )详解
- 进程间通信方式
- 基于springboot 之jsp章节
- android SD卡检测和热插拔功能
- 三次握手四次挥手状态
- 2017暑假第二阶段第一场 总结
- oracle 学习笔记
- 登录令牌Token介绍
- 1295开发板, 带HDMI录像, OpenWRT + Android 6.0 双系统
- HDU 1525 Euclid’s Game
- ZooKeeper客户端线程模型学习
- 万用表二极管档和三极管档的使用
- Postfix邮件服务器搭建之虚拟用户配置
- andoid搭建开发环境之初学者的福音