1.最小差值
排序枚举
int a[N];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
int ans=0x3f3f3f3f;
for(int i=1;i<n;i++)
ans=min(ans,a[i]-a[i-1]);
cout<<ans;
}
2.游戏
约瑟夫环
bool is(int m,int k){
return m%k==0||m%10==k;
}
int main(){
vector<int> v;
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
v.push_back(i);
int m=1;//当前报的数
int p=0;//数组下标
while(v.size()!=1){
if(is(m,k)){
v.erase(v.begin()+p);
p--;
}
m++;
p++;
p%=v.size();
}
cout<<v[0];
}
y总的代码: 用队列确实要快不少
bool is(int x,int k){
return x%k==0||x%10==k;
}
int main(){
int n,k;
cin>>n>>k;
queue<int> q;
for(int i=1;i<=n;i++)
q.push(i);
int j=1; //j记录当前时间
while(q.size()>1){
int t=q.front();
q.pop();
if(!is(j++,k)) q.push(t);
}
cout<<q.front();
}
3.Crontab
注意到n最大是20,所以每次可以枚举时间,然后再枚举每个Crontab,看看是否符和要求即可
具体实现:
- 实现一个date类,每次对该date类加一分钟
- 实现一个Crontab类,用字符串来构造Crontab,实现给一个date,Crontab可以判断是否是自己的合法时间
- 枚举所有date即可
但是模拟过程太复杂了试着敲敲吧
y总的日期时间模拟题模板:
int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool is_leap(){
return year%400==0||(year%4==0&&year%100!=0);
}
int get_month(){
if(month==2) return months[2]+is_leap();
return months[month];
}
void next(){
if(++mintues>=60){
mintues=0;
if(++hours>=24){
hours=0;
week=(++week)%7;
if(++day>get_month()){
day=1;
if(++month>=13){
month=1;
year++;
}
}
}
}
}
main(){
// t为被枚举的时间,e为终止时间,s为题目给定的起始时间
while(t<e){
if(!(t<s)){
/*
函数体
*/
}
t.next();
}
}
题目的坑梳理一下:
- 时间从1970年开始的,而不是1900年
- 二月是28天,而不是30天(这其实是我自己的问题,在这里卡了很久)
#include<iostream>
#include<sstream>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define N 1010
int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
struct date{
bool is_leap(){
return year%400==0||(year%4==0&&year%100!=0);
}
int get_month(){
if(month==2) return months[2]+is_leap();
return months[month];
}
int year,month,day,hours,mintues,week;
date(const string &s){
sscanf(s.c_str(),"%04d%02d%02d%02d%02d",&year,&month,&day,&hours,&mintues);
}
bool operator<(const date& dt) const{
if(year!=dt.year) return year<dt.year;
if(month!=dt.month) return month<dt.month;
if(day!=dt.day) return day<dt.day;
if(hours!=dt.hours) return hours<dt.hours;
return mintues<dt.mintues;
}
void next(){
if(++mintues>=60){
mintues=0;
if(++hours>=24){
hours=0;
week=(++week)%7;
if(++day>get_month()){
day=1;
if(++month>=13){
month=1;
year++;
}
}
}
}
}
void out(){
printf("%04d%02d%02d%02d%02d",year,month,day,hours,mintues);
}
};
string mon_str[13]={"","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"};
string week_str[7]={"sun","mon","tue","wed","thu","fri","sat"};
void lower(string &s){
for(int i=0;i<s.length();i++){
if(s[i]>='A'&&s[i]<='Z') s[i]+='a'-'A';
}
}
struct Crontab{
set<int> mintues,hours,day,month,week;
string command;
int to_int(const string &s){
int ans=0;
for(int i=0;i<s.length();i++)
ans=ans*10+s[i]-'0';
return ans;
}
int fnd(string s){
lower(s);
for(int i=0;i<13;i++)
if(s==mon_str[i]) return i;
for(int i=0;i<7;i++)
if(s==week_str[i]) return i;
return to_int(s);
}
void solve(const string &s,set<int> &st,int start,int end){
if(s=="*")
{
for(int i=start;i<=end;i++)
st.insert(i);
}
else
for(int i=0;i<s.length();){
int j=i;
while(j<s.length()&&(s[j]>='0'&&s[j]<='9'||s[j]>='a'&&s[j]<='z'||s[j]>='A'&&s[j]<='Z')) j++;
if(j>=s.length()) {
st.insert(fnd(s.substr(i,j-i)));
i=j;
}else if(s[j]==','){
st.insert(fnd(s.substr(i,j-i)));
j++;
i=j;
}else {
int k=j+1;
while(k<s.length()&&(s[k]>='0'&&s[k]<='9'||s[k]>='a'&&s[k]<='z'||s[k]>='A'&&s[k]<='Z')) k++;
int l=fnd(s.substr(i,j-i));
int r=fnd(s.substr(j+1,k-j-1));
for(int p=l;p<=r;p++)
st.insert(p);
i=k+1;
}
}
}
Crontab(const string &s){
stringstream ss(s);
string temp;
ss>>temp;
solve(temp,mintues,0,59);
ss>>temp;
solve(temp,hours,0,23);
ss>>temp;
solve(temp,day,1,31);
ss>>temp;
solve(temp,month,1,12);
ss>>temp;
solve(temp,week,0,6);
ss>>temp;
command=temp;
}
bool in(date &dt){
return mintues.find(dt.mintues)!=mintues.end()&&hours.find(dt.hours)!=hours.end()&&day.find(dt.day)!=day.end()&&month.find(dt.month)!=month.end()&&week.find(dt.week)!=week.end();
}
};
vector<Crontab> vec;
int main(){
int n;
string start,end;
cin>>n>>start>>end;
date s(start),e(end);
getchar();
for(int i=0;i<n;i++){
string temp;
getline(cin,temp);
vec.push_back(Crontab(temp));
}
date t("197001010000"); //1970年1月1日0时0点 星期四
t.week=4;
while(t<e){
if(!(t<s)){
for(int i=0;i<vec.size();i++){
if(vec[i].in(t)){
t.out();
cout<<" "<<vec[i].command<<endl;
}
}
}
t.next();
}
}
4.行车路线:
因为题目中有:
保证答案不超过10的6次方
所以小路长度绝对不超过1000
可以设一个数组dis[n][1010]
dis[i][j]记为遍历到i点时上一条小路长度为j时的疲劳值
用优先队列去更新即可
但是要注意:
bfs一般有两种模板,第一种是将判断条件放在q.pop之后的,这种模板比较好写,但是容易超时
第二种就是下边这种模板,比较难想也不好敲,因此可以先敲模板1,超时了再换成模板2即可
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
#define N 510
struct node{
int to,val;
int t;//最后一条小路的长度 或 路的类型
bool operator<(const node &n)const{
return val>n.val;
}
};
vector<node> G[N];
int dis[N][1010];
bool vis[N][1010];
// dis[i][j]记为到达点i且最后一条小路长度为j的疲劳值
void dijistra(){
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
priority_queue<node> q;
q.push((node){1,0,0});
while(q.size()){
node f=q.top();
q.pop();
for(int i=0;i<G[f.to].size();i++){
node &nxt=G[f.to][i];
if(nxt.t){//小道
int len=(nxt.val+f.t);
int newdis=f.val-f.t*f.t+len*len;
if(len<=1000&&dis[nxt.to][len]>newdis&&newdis<=1000000){
q.push((node){nxt.to,newdis,nxt.val+f.t});
dis[nxt.to][len]=newdis;
}
}else{
int newdis=f.val+nxt.val;
if(dis[nxt.to][0]>newdis&&newdis<=1000000){
q.push((node){nxt.to,newdis,0});
dis[nxt.to][0]=newdis;
}
}
}
}
}
int main(){
int n,m;
cin>>n>>m;
while(m--){
int t,a,b,c;
cin>>t>>a>>b>>c;
G[a].push_back((node){b,c,t});
G[b].push_back((node){a,c,t});
}
dijistra();
int ans=INF;
for(int i=0;i<1010;i++){
ans=min(ans,dis[n][i]);
}
cout<<ans;
}