acm暑期集训_2020.07.02
任务清单
1、 回顾ZUCC蓝桥杯热身赛-1中A、B、C题中涉及的知识点
2、 补题-----ZUCC蓝桥杯热身赛-1中D题
A题------洛谷-P1548 棋盘问题(入门)
思维题,做题要快
B题------洛谷-P1042 乒乓球(普及-)
题目总体难度不难,主要是读入的时候怎样处理文件读入型字符串
该题目的输入格式:
每个输入文件包含若干行字符串,字符串有大写的W、L和E组成。其中E表示比赛信息结束,程序应该忽略E之后的所有内容。
输入格式:
WWWWWWWWWWWWWWWWWWWW
WWLWE
// freopen("in.txt","r",stdin); //用freopen判断测试用例
while(~scanf("%[^\n]\n",ch+len)){
int tlen=strlen(ch+len);
len+=tlen;
}//通过这样的形式就可以把文件中一行行的字符串都读入到ch这个总的字符串中了
C题------洛谷–P2010回文日期(普及-)
1、 回顾了很久没用的 sprintf和sscanf函数的使用
for(int i=0;i<10000;i++){//实现回文串的构造 (根据年份即可推出月日)
sprintf(ch,"%04d%d%d%d%d",i,i%10,i%100/10,i%1000/100,i/1000);
sscanf(ch,"%*04d%02d%02d",&m,&d);//sscanf中%*04d的用法:*按照格式读取,但是不存,04d取四位
if(pdr(i)){
if(m>=1&&m<=12&&d>=1&&d<=d2[m]){
vec.push_back(i*10000+m*100+d);
}
}
else{
if(m>=1&&m<=12&&d>=1&&d<=d1[m]){
vec.push_back(i*10000+m*100+d);
}
}
}
2、 回顾了lower_bound和upper_bound函数的使用
int ta=lower_bound(vec.begin(),vec.end(),a)-vec.begin();//通过减去起始位置的方法,ta得到的是对应在vec里的位置下标
int tb=upper_bound(vec.begin(),vec.end(),b)-vec.begin();
// int tb=lower_bound(vec.begin(),vec.end(),b)-vec.begin();
printf("%d\n",tb-ta);
lower_bound和upper_bound均利用了二分查找算法,在一个数组中进行查数,通过数组下标相减的方法就可以知道对应区间存在的个数了。
lower_bound(begin,end,x)-数组名。从begin位置到end-1位置,查找第一个大于等于x的数的位置。如果不存在,返回的是end
upper_bound(begin,end,x)-数组名。从begin位置到end-1位置,查找第一个大于x的数的位置。如果不存在,返回的是end
这里要特别注意,为了防止用lower_bound/upper_bound查找时会有跑出边界的情况发生,在放入第一个数之前在vector里放入一个最小临界点,在放完所有数之后在vector里放入一个最大临界点。
vec.push_back(0);//插入最小临界点
for(int i=0;i<10000;i++){
sprintf(ch,"%04d%d%d%d%d",i,i%10,i%100/10,i%1000/100,i/1000);
sscanf(ch,"%*04d%02d%02d",&m,&d);
if(pdr(i)){
if(m>=1&&m<=12&&d>=1&&d<=d2[m]){
vec.push_back(i*10000+m*100+d);
}
}
else{
if(m>=1&&m<=12&&d>=1&&d<=d1[m]){
vec.push_back(i*10000+m*100+d);
}
}
}
vec.push_back(100000000);插入最大临界点
D题------洛谷–P1073 最优贸易(提高+/省选-)
方法一:暴力+动规,主要注意的是,在dfs深搜时要考虑清楚退出时的情况,运用好标记。
#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,z;
int c[100007],mi[100007],dp[100007];
vector<int> vec[100007];
void dfs(int x,int pr,int Min){
int bz=1;//退出递归的标志
Min=min(c[x],Min);//记录目前访问过的结点中的最小值
if(mi[x]>Min){
mi[x]=Min;//数组mi用于记录结点x可以到达的最小值,用于计算之后差值
bz=0;
} //更新操作,继续递归
int Max=max(dp[pr],c[x]-mi[x]);//数组dp动态规划,求到达该节点的最大差额
if(dp[x]<Max){
dp[x]=Max;
bz=0;
} //更新操作,继续递归
if(bz==1) return;//该题目中存在环路,为了防止在dfs环路中爆栈,遇到访问过的节点就退出
for(int i=0;i<vec[x].size();i++){
dfs(vec[x][i],x,Min);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&c[i]);
}
for(int i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
vec[x].push_back(y);
if(z==2){
vec[y].push_back(x);
}
}
memset(mi,0x3f3f3f3f,sizeof(mi));
dfs(1,0,0x3f3f3f3f);
printf("%d\n",dp[n]);
}
方法二:两遍SPFA
方法三:tarjan缩点+拓扑排序+DP
具体题解洛谷上有,明天的第一项任务就是了解SPFA和tarjan缩点咯