21-22-1蓝桥训练9
补充本周蓝桥CE两题。
题目
C、试题 算法提高 合并石子
思路:
本题是区间dp的经典例题,当然石子合并问题还有很多的变化,也有一些神奇的优化方法,有兴趣的大佬可以自己去学习一下(这里我给出连接:石子合并问题–动态规划;贪心)
这里我用的是(GarsiaWachs算法)
#include <fstream>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N = 50005;
const int INF = 0x3f3f3f3f;
int stone[N];
int n,t,ans;
void combine(int k)
{
int tmp = stone[k] + stone[k-1];
ans += tmp;
t--;
for(int i=k;i<t;i++)
stone[i] = stone[i+1];
int j = 0;
for(j=k-1;stone[j-1] < tmp;j--)
stone[j] = stone[j-1];
stone[j] = tmp;
while(j >= 2 && stone[j] >= stone[j-2])
{
int d = t - j;
combine(j-1);
j = t - d;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&stone[i]);
stone[0]=INF;
stone[n+1]=INF-1;
t = 3;
ans = 0;
for(int i=3;i<=n+1;i++)
{
stone[t++] = stone[i];
while(stone[t-3] <= stone[t-1])
combine(t-2);
}
while(t > 3) combine(t-1);
printf("%d\n",ans);
memset(stone,0,sizeof(stone));
return 0;
}
E、试题 算法提高 Intersecting Dates
题意:
简单的说,已知nx个时间区间中的每一天,但是要求知道nr个时间区间中的每一天,问需要
新增出几个时间区间,才能到达要求。
如果时间区间只有一天的话,输出该天时间即可,格式:** 月/日/年**(前面四个空格)
否则输出区间开始时间和结束时间。格式** 月/日/年 to 月/日/年**(前面四个空格,第一个月/日/年是开始时间,第二个月/日/年是结束时间)
要是没有新增时间区间,输出** No additional quotes are required.**(前面四个空格)
思路:
直接模拟就行了,我们可以将1700年到2100年中的每一天按顺序转化成数字,然后先记录一下已知区间,随后在读入要求区间的时间将区间对应的每一个数字标记一下,之后再用已知区间将可以消除标记的数字全部删除。最后仍然处于标记状态的数字就是要新增的时间。
同时,我们通过全局变量flag来判断是否有新增区间,没有就输出** No additional quotes are required.**,
两个小细节:
①:每次我们都应该初始化flag和对标记数组vis进行清空。
②:每次询问后要多输出一次换行,不然过不了全部数据。(根据红色框框得出)
#include<bits/stdc++.h>
using namespace std;
const int N=105;
int t,nx,nr;
int st[N],ed[N];
bool flag;
int days[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool vis[150000]; //400*366=146400
bool cek(int x){return (x%4==0&&x%100!=0)||(x%400==0);}
int change(int x){
int year=x/10000;
int month=(x%10000)/100;
int day=x%100;
int sum=0;
for(int i=1700;i<year;i++){
if(cek(i)) sum+=366;
else sum+=365;
}
if(cek(year)) days[2]=29;
else days[2]=28;
for(int i=1;i<month;i++) sum+=days[i];
sum+=day;
return sum;
}
void get_vis(int start,int end,int type){
int st1=change(start);
int ed1=change(end);
for(int i=st1;i<=ed1;i++) vis[i]=type;
}
void change1(int x,bool kind){
int year=1700,month=0,day=0,hv=0,te;
while(1){
if(cek(year)) te=366;
else te=365;
if(hv+te>x) break;
year++,hv+=te;
}
if(hv==x){
year--;
month=12;
day=31;
}
else{
if(cek(year)) days[2]=29;
else days[2]=28;
for(int i=1;i<=12;i++){
if(hv+days[i]>x) break;
month++,hv+=days[i];
}
if(hv==x) day=days[month];
else month++,day=x-hv;
// if(hv==x) day=days[month];
// else day=x-hv;
}
printf("%d/%d/%d",month,day,year);
if(kind) puts("");
}
void solve(int ci){
printf("Case %d:\n",ci);
for(int i=1;i<150000;i++) vis[i]=false;
for(int i=1;i<=nx;i++) scanf("%d%d",&st[i],&ed[i]);
for(int i=1;i<=nr;i++){
int start,end; scanf("%d%d",&start,&end);
get_vis(start,end,1);
}
for(int i=1;i<=nx;i++) get_vis(st[i],ed[i],0);
for(int i=1;i<150000;i++){
if(vis[i]){
flag=true;
printf(" ");
if(!vis[i+1]) change1(i,true);
else{
change1(i,false);
printf(" to ");
for(int j=i+1;j<150000;j++){
// cout<<"j="<<j<<"\n";
if(vis[j]) continue;
else {change1(j-1,true);i=j-1;break;}
}
}
}
}
if(!flag) puts(" No additional quotes are required.");
puts("");
}
int main(){
while(scanf("%d%d",&nx,&nr)){
if(nx==0&&nr==0) return 0;
t++; flag=false;
solve(t);
}
}