基础算法
递推
AcWing 5556. 牛的语言学 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
const int N=5e4+10;
string s;
bool f[N];
int main(){
cin>>s;
int n=s.size();
set<string> res;
f[n-1]=true;
for(int i=n-3;i>=4;i--){
for(int j=2;j<=3;j++){
if(f[i+j]){
string a=s.substr(i+1,j);
string b=s.substr(i+j+1,j);
if(a!=b||f[i+5]){
f[i]=true;
res.insert(a);
}
}
}
}
cout<<res.size()<<endl;
for(auto& t:res) cout<<t<<endl;
return 0;
}
AcWing 95. 费解的开关 入口
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=6;
int n;
char square[N][N],backup[N][N]; //square ÓÃÀ´¼Ç¼·½ÐξØÕóµÄ±ä»¯£¬backup ÓÃÀ´¼Ç¼Ա¾µÄ·½ÐξØÕó
int dx[N]={0,0,1,0,-1},dy[N]={0,1,0,-1,0};
void turn(int x,int y){
for(int i=0;i<5;i++){
int a=x+dx[i],b=y+dy[i];
if(a<0||a>=5||b<0||b>=5)continue;
square[a][b]^=1;
}
}
int main(){
cin>>n;
while(n--){
int ans=10;
//ÓÃÀ´»ñµÃÔ±¾·½ÐξØÕó
for(int i=0;i<5;i++){
cin>>backup[i];
}
//¶ÔËùÓÐÇé¿ö½øÐбéÀú
for(int op=0;op<32;op++){
memcpy(square,backup,sizeof backup); //½«backupµÄ¼Ç¼µ½suqareÉÏÔÙÖ´ÐУ¬¾Í²»Óûָ´ÏÖ³¡ÁË
int step=0;
//¶ÔµÚÒ»²ã½øÐбéÀú
for(int i=0;i<5;i++){
if(op>>i&1){
step++;
turn(0,i);
}
}
//¶ÔÆäËû²ã½øÐзת
for(int i=1;i<5;i++){
for(int j=0;j<5;j++){
if(square[i-1][j]=='0'){
step++;
turn(i,j);
}
}
}
bool dark=false;
//¶Ô×îºóÒ»²ã½øÐÐÊÇ·ñÓÐÁÁµÆÅжÏ
for(int j=0;j<5;j++){
if(square[4][j]=='0'){
dark=true;
break;
}
}
if(!dark)
ans=min(ans,step);
}
if(ans>6)ans=-1;
printf("%d\n",ans);
}
return 0;
}
归并排序
AcWing 787. 归并排序 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100010;
int n,a[N];
bool cmp(int x,int y){
return x<=y;
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n,cmp);
for(int i=0;i<n;i++) cout<<a[i]<<" ";
return 0;
}
AcWing 788. 逆序对的数量 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=100010;
int n,a[N],tmp[N];
LL merge_sort(int l,int r){
if(l>=r) return 0;
int mid=l+r>>1;
LL rres=0;
rres+=merge_sort(l,mid)+merge_sort(mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r){
if(a[i]<=a[j]) tmp[k++]=a[i++];
else{
tmp[k++]=a[j++];
rres+=mid-i+1;
}
}
while(i<=mid) tmp[k++]=a[i++];
while(j<=r) tmp[k++]=a[j++];
for(int x=l,y=0;x<=r;x++,y++) a[x]=tmp[y];
return rres;
}
int main(){
cin>>n;
for(int i=0;i<n;i++) scanf("%d",&a[i]);
LL res=merge_sort(0,n-1);
printf("%ld",res);
return 0;
}
二分
第14届蓝桥杯c试题:冶炼金属 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e4+10;
int n,a[N],b[N];
int minv,maxv;
bool checkMax(int x){
for(int i=0;i<n;i++){
if(a[i]/x<b[i])
return false;
}
return true;
}
bool checkMin(int x){
for(int i=0;i<n;i++){
if(a[i]/x>b[i])
return false;
}
return true;
}
int main(){
cin>>n;
for(int i=0;i<n;i++) scanf("%d%d",&a[i],&b[i]);
int l=1,r=1e9;
while(l<r){
int mid=(l+r)>>1;
if(checkMin(mid)) r=mid;
else l=mid+1;
}
minv=r;
l=1,r=1e9;
while(l<r){
int mid=(l+r+1)>>1;
if(checkMax(mid)) l=mid;
else r=mid-1;
}
maxv=r;
printf("%d %d",minv,maxv);
return 0;
}
AcWing 5562. 最大生产 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
using namespace std;
typedef long long LL;
const int N=100010;
int n,k,a[N],b[N];
bool check(LL x){
int t=k;
for(int i=0;i<n;i++){
if(t+b[i]<a[i]) return false;
if(a[i]*x>b[i]){
if(t<a[i]*x-b[i]) return false;
else t-=a[i]*x-b[i];
}
if(t<0) return false;
}
return true;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++) scanf("%d",&b[i]);
LL l=0;
LL r=INT_MAX;
while(l<r){
LL mid=(l+r+1)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%d",r);
return 0;
}
AcWing 5566. 盖楼 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2e9+100;
typedef long long LL;
int n,m,x,y;
bool check(LL mid){
LL a=mid/y-mid/x/y;
LL b=mid/x-mid/x/y;
LL c=mid-mid/x-mid/y+mid/x/y;
LL s1=max(0ll,n-a),s2=max(0ll,m-b);
return s1+s2<=c;
}
int main(){
cin>>n>>m>>x>>y;
LL l=0,r=3e9;
while(l<r){
LL mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d",r);
return 0;
}
前缀和
AcWing 99. 激光炸弹 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5010;
int n,r,x,y,w,s[N][N];
int main()
{
//ÊäÈë
cin>>n>>r;
r=min(5001,r);
for(int i=0;i<n;i++)
{
cin>>x>>y>>w;
s[++x][++y]+=w;
}
//±ä»»¸ñʽ
for(int i=1;i<N;i++)
for(int j=1;j<N;j++)
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
//Êä³ö
int ans=0;
for(int i=r;i<N;i++)
for(int j=r;j<N;j++)
{
ans=max(ans,s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r]);
}
printf("%d",ans);
return 0;
}
入口AcWing 1230. K倍区间 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,k,x,cnt[N],s[N];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>x;
s[i]=s[i-1]+x;
}
int ans=0;
cnt[0]=1;
for(int i=1;i<=n;i++)
{
ans+=cnt[(int)(s[i]%k)];
cnt[(int)(s[i]%k)]++;
}
cout<<ans;
return 0;
}
差分
AcWing 503. 借教室 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
struct Order{
int d,s,t;
};
const int N=1000010;
int a[N];
Order order[N];
int n,m;
LL b[N];
bool check(int x){
memset(b,0,sizeof b);
for(int i=1;i<=x;i++){
b[order[i].s]+=order[i].d;
b[order[i].t+1]-=order[i].d;
}
LL s=0;
for(int i=1;i<=n;i++){
s+=b[i];
if(s>a[i]) return false;
}
return true;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d%d%d",&order[i].d,&order[i].s,&order[i].t);
int l=0,r=m;
while(l<r){
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
if(r==m){
printf("0");
}
else printf("-1\n%d\n",r+1);
return 0;
}
AcWing 4262. 空调 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100010;
int a[N],b[N];
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
b[i]=a[i]-x;
}
for(int i=0;i<=n;i++) b[i]=b[i+1]-b[i];
int res=0;
for(int i=0;i<=n;i++){
if(b[i]>0) res+=b[i];
}
printf("%d",res);
return 0;
}
离散化
AcWing 505. 火柴排队 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100010,MOD=99999997;
int n;
int a[N],b[N],tmp[N],p[N],c[N];
int merge_sort(int l,int r){
if(l>=r) return 0;
int mid=l+r>>1;
int res=(merge_sort(l,mid)+merge_sort(mid+1,r))%MOD;
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r){
if(b[i]<b[j]) tmp[k++]=b[i++];
else{
tmp[k++]=b[j++];
res=(res+mid-i+1)%MOD;
}
}
while(i<=mid) tmp[k++]=b[i++];
while(j<=r) tmp[k++]=b[j++];
for(int i=l,j=0;i<=r;i++,j++) b[i]=tmp[j];
return res;
}
void work(int a[]){
for(int i=1;i<=n;i++) p[i]=i;
sort(p+1,p+n+1,[&](int x,int y){
return a[x]<a[y];
});
for(int i=1;i<=n;i++) a[p[i]]=i;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
work(a);
work(b);
for(int i=1;i<=n;i++) c[a[i]]=i;
for(int i=1;i<=n;i++) b[i]=c[b[i]];
printf("%d",merge_sort(1,n));
return 0;
}
区间合并
AcWing 1343. 挤牛奶 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5010;
int n;
struct Farmer{
int s,e;
bool operator <(const Farmer &t) const{
if(s<t.s) return true;
else return false;
}
}farmer[N];
int main(){
//ÊäÈë
cin>>n;
for(int i=0;i<n;i++) scanf("%d%d",&farmer[i].s,&farmer[i].e);
//ÅÅÐò
sort(farmer,farmer+n);
//´¦Àí
int max_cont=0;
int max_diet=0;
int l=farmer[0].s;
int r=farmer[0].e;
for(int i=1;i<n;i++){
if(farmer[i].s<=r) r=max(r,farmer[i].e);
else{
max_cont=max(max_cont,r-l);
max_diet=max(max_diet,farmer[i].s-r);
l=farmer[i].s,r=farmer[i].e;
}
}
max_cont=max(max_cont,r-l);
printf("%d ",max_cont);
printf("%d\n",max_diet);
return 0;
}
枚举
第13届蓝桥杯D试题:修剪灌木 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10010;
int main(){
int n;
cin>>n;
int max=2*n-2;
for(int i=0;i<n;i++){
if(i<(n+1)/2){
printf("%d\n",max-2*i);
}else{
printf("%d\n",max-2*(n-i-1));
}
}
return 0;
}
数据结构
并查集
AcWing 5557. 孤立点数量 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=3e5;
int n,m,res;
int p[N];
bool str[N]; //ÓÃÀ´ÅжϵãiÊÇ·ñ´¦ÓÚ»·ÄÚ
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++) p[i]=i;
while(m--){
int a,b;
scanf("%d%d",&a,&b);
a=find(a),b=find(b);
if(a==b) str[a]=true;
else p[a]=b,str[b]|=str[a];
}
for(int i=0;i<n;i++){
if(p[i]==i&&!str[i])
res++;
}
printf("%d",res);
return 0;
}
AcWing 528. 奶酪 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1010;
struct Node{
int x,y,z;
}q[N*N];
int n,h,r;
int p[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main(){
int t;
cin>>t;
while(t--){
scanf("%d%d%d",&n,&h,&r);
for(int i=0;i<=n+1;i++){
p[i]=i;
}
for(int i=1;i<=n;i++){
scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
if(abs(q[i].z)<=r) p[find(i)]=find(0);
if(abs(q[i].z-h)<=r) p[find(i)]=p[find(n+1)];
}
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(i!=j){
LL dx=q[i].x-q[j].x;
LL dy=q[i].y-q[j].y;
LL dz=q[i].z-q[j].z;
if(dx*dx+dy*dy+dz*dz<=4*(LL)r*r){
p[find(i)]=find(j);
}
}
}
}
if(p[find(0)]==p[find(n+1)]){
printf("Yes\n");
}else{
printf("No\n");
}
}
return 0;
}
搜索
DFS
第14届蓝桥杯F试题:岛屿个数 入口
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=55;
int n,m,ans;
int g[N][N];
bool str[N][N];
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
void find(int x,int y){
str[x][y]=true;
for(int i=0;i<4;i++){
int xx=dx[i]+x,yy=dy[i]+y;
if(!str[xx][yy]&&g[xx][yy]==1) find(xx,yy);
}
}
void dfs(int x,int y){
str[x][y]=true;
for(int i=x-1;i<=x+1;i++)
for(int j=y-1;j<=y+1;j++){
if(i<0||i>n+1||j<0||j>m+1||str[i][j]) continue;
if(g[i][j]==0) dfs(i,j);
else find(i,j),ans++;
}
}
int main(){
int t;
cin>>t;
while(t--){
memset(g, 0, sizeof g);
memset(str, false, sizeof str);
ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;
cin>>c;
g[i][j]=c-'0';
}
}
dfs(0,0);
printf("%d\n",ans);
}
return 0;
}
第12届蓝桥杯G试题:砝码称重 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=110,B = 200010, M = B / 2;
int n,m,res;
int w[N];
bool f[N][B];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
m+=w[i];
}
f[0][M]=true;
for(int i=1;i<=n;i++){
for(int j=-m;j<=m;j++){
f[i][j+M]=f[i-1][j+M];
if(j-w[i]>=-m) f[i][j+M]|=f[i-1][j-w[i]+M];
if(j+w[i]<=m) f[i][j+M]|=f[i-1][j+w[i]+M];
}
}
for(int j=1;j<=m;j++){
if(f[n][j+M]) res++;
}
printf("%d",res);
return 0;
}
BFS
AcWing 1101. 献给阿尔吉侬的花束 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=210;
char st[N][N];
PII Start,End;
int tr[N][N];
int r,c;
int bfs(PII start,PII end){
queue<PII> q;
int tx[4]={1,0,-1,0},ty[4]={0,1,0,-1};
memset(tr,-1,sizeof tr);
tr[start.x][start.y]=0;
q.push(start);
while(q.size()){
PII t=q.front();
q.pop();
for(int i=0;i<4;i++){
int x=t.x+tx[i],y=t.y+ty[i];
if(x<0||x>=r||y<0||y>=c) continue;
if(st[x][y]=='#') continue;
if(tr[x][y]!=-1) continue;
tr[x][y]=tr[t.x][t.y]+1;
if(end==make_pair(x,y)) return tr[x][y];
q.push({x,y});
}
}
return -1;
}
int main(){
int T;
cin>>T;
while(T--){
cin>>r>>c;
memset(st,0,sizeof st);
for(int i=0;i<r;i++) scanf("%s",&st[i]);
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
if(st[i][j]=='S') Start.x=i,Start.y=j;
else if(st[i][j]=='E') End.x=i,End.y=j;
}
}
int dis=bfs(Start,End);
if(dis==-1){
printf("oop!\n");
}else printf("%d\n",dis);
}
return 0;
}
AcWing 1096. 地牢大师 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
struct Point{
int x,y,z;
};
const int N=105;
int l,r,c;
char g[N][N][N]; //存地图
int dis[N][N][N]; //用来得到该地点是否被访问过
int dx[]={1,-1,0,0,0,0},dy[]={0,0,1,-1,0,0},dz[]={0,0,0,0,1,-1};
int bfs(Point start){
queue<Point> q;
dis[start.x][start.y][start.z]=0;
q.push(start);
while(q.size()){
Point t=q.front();
q.pop();
for(int i=0;i<6;i++){
int x=t.x+dx[i];
int y=t.y+dy[i];
int z=t.z+dz[i];
if(x<0||x>=l||y<0||y>=r||z<0||z>=c) continue; //出界
if(dis[x][y][z]!=-1 ) continue; //被访问过
if(g[x][y][z]=='#') continue; //墙
dis[x][y][z]=dis[t.x][t.y][t.z]+1;
if(g[x][y][z]=='E') return dis[x][y][z];
q.push({x,y,z});
}
}
return -1;
}
int main(){
while(scanf("%d%d%d",&l,&r,&c),l||r||c){
Point start;
memset(dis,-1,sizeof dis);
memset(g,0,sizeof g);
for(int i=0;i<l;i++){
for(int j=0;j<r;j++){
scanf("%s",g[i][j]);
for(int z=0;z<c;z++){
if(g[i][j][z]=='S') start.x=i,start.y=j,start.z=z;
}
}
}
int distance=bfs(start);
if(distance==-1){
printf("Trapped!\n");
}else{
printf("Escaped in %d minute(s).\n",distance);
}
}
return 0;
}
图论
拓扑排序
AcWing 5563. 自定义字典序 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=110,M=30;
int n;
string s[N];
bool g[M][M];
int d[N],q[N];
bool work(string& s1,string& s2){
for(int i=0;i<s1.size()&&i<s2.size();i++){
if(s1[i]!=s2[i]){
int x=s1[i]-'a';
int y=s2[i]-'a';
g[x][y]=true;
return true;
}
}
return s1<s2;
}
bool topsort(){
int hh=0,tt=-1;
for(int i=0;i<26;i++){
if(!d[i]){
q[++tt]=i;
}
}
while(hh<=tt){
int t=q[hh++];
for(int i=0;i<26;i++){
if(g[t][i]){
d[i]--;
if(!d[i]){
q[++tt]=i;
}
}
}
}
return tt==25;
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>s[i];
}
for(int i=0;i<n-1;i++){
if(!work(s[i],s[i+1])){
printf("Impossible");
return 0;
}
}
for(int i=0;i<26;i++){
for(int j=0;j<26;j++){
if(g[i][j]){
d[j]++;
}
}
}
if(!topsort()) printf("Impossible");
else{
for(int i=0;i<26;i++){
cout<<(char)(q[i]+'a');
}
}
return 0;
}
数学
最大公约数
AcWing 4199. 公约数 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1350;
int a,b,q;
int p[N];
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
scanf("%d%d%d",&a,&b,&q);
int cnt=0;
int d=gcd(a,b);
for(int i=1;i<=d/i;i++){
if(d%i==0){
p[cnt++]=i;
if(i!=d/i) p[cnt++]=d/i;
}
}
sort(p,p+cnt,greater<int>());
while(q--){
int l,r;
bool find=false;
scanf("%d%d",&l,&r);
for(int i=0;i<N;i++){
if(!p[i]) break;
if(r>=p[i]&&p[i]>=l){
find=true;
printf("%d\n",p[i]);
break;
}
}
if(!find) printf("-1\n");
}
return 0;
}
AcWing 1246. 等差数列 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100010;
int n,a[N];
int gcd(int a,int b){
return b? gcd(b,a%b):a;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
int d=0;
for(int i=2;i<=n;i++){
d=gcd(d,(a[i]-a[1]));
}
if(!d){
printf("%d",n);
}else{
printf("%d",(a[n]-a[1])/d+1);
}
return 0;
}
AcWing 1360. 有序分数 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define x first
#define y second
using namespace std;
const int N=160;
int n;
typedef pair<int,int> PII;
PII p[N*N];
int gcd(int i,int j){
return j?gcd(j,i%j):i;
}
bool cmp(PII a,PII b){
return a.x*b.y<a.y*b.x;
}
int main(){
cin>>n;
int cnt=0;
for(int j=1;j<=n;j++){
for(int i=0;i<=j;i++)
if(gcd(i,j)==1){
p[cnt++]={i,j};
}
}
sort(p,p+cnt,cmp);
for(int i=0;i<cnt;i++) printf("%d/%d\n",p[i].x,p[i].y);
return 0;
}
容斥原理
AcWing 5566. 盖楼 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2e9+100;
typedef long long LL;
int n,m,x,y;
bool check(LL mid){
LL a=mid/y-mid/x/y;
LL b=mid/x-mid/x/y;
LL c=mid-mid/x-mid/y+mid/x/y;
LL s1=max(0ll,n-a),s2=max(0ll,m-b);
return s1+s2<=c;
}
int main(){
cin>>n>>m>>x>>y;
LL l=0,r=3e9;
while(l<r){
LL mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d",r);
return 0;
}
动态规划
背包问题
AcWing 2. 01背包问题 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&w[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
if(j>=v[i]) f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
}
}
printf("%d",f[n][m]);
return 0;
}
AcWing 3. 完全背包问题 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&w[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
if(j>=v[i]) f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
}
}
printf("%d",f[n][m]);
return 0;
}
线性dp
第14届蓝桥杯E试题:接龙数列 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,l[N],r[N];
char num[16];
int f[N],g[10];
int main(){
cin>>n;
int res=0;
for(int i=0;i<n;i++){
scanf("%s",num);
l[i]=num[0]-'0',r[i]=num[strlen(num)-1]-'0';
}
for(int i=0;i<n;i++){
f[i]=1;
f[i]=max(f[i],g[l[i]]+1);
g[r[i]]=max(g[r[i]],f[i]);
res=max(f[i],res);
}
printf("%d",n-res);
return 0;
}
Acwing 895. 最长上升子序列 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1010;
int n,a[N],res;
int f[N];
int main(){
cin>>n;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<n;i++){
f[i]=1;
for(int j=0;j<i;j++){
if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
}
res=max(res,f[i]);
}
printf("%d",res);
return 0;
}
区间dp
AcWing 1222. 密码脱落 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1010;
char w[N];
int f[N][N];
int main(){
scanf("%s",w+1);
int n=strlen(w+1);
for(int len=1;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
if(len==1) f[i][j]=1;
else{
f[i][j]=max(f[i+1][j],f[i][j-1]);
if(w[i]==w[j]){
f[i][j]=max(f[i][j],f[i+1][j-1]+2);
}
}
}
}
printf("%d",n-f[1][n]);
return 0;
}
压缩dp
第13届蓝桥杯G试题:接龙数列 入口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e7+10,MOD=1e9+7;
int n;
int f[N][4];
int g[4][4]={
{1,1,1,1},
{0,0,1,1},
{0,1,0,1},
{1,0,0,0},
};
int main(){
cin>>n;
f[1][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<4;j++){
for(int k=0;k<4;k++){
f[i+1][k]=(f[i+1][k]+f[i][j]*g[j][k])%MOD;
}
}
}
printf("%d",f[n+1][0]);
return 0;
}
日期问题
第14届蓝桥杯A试题:日期统计 入口
#include<bits/stdc++.h>
using namespace std;
int a[41]={3,8,5,1,6,3,4,6,7,0,7,8,2,7,6,8,9,5,6,5,6,1,4,0,1,0,0,9,4,8,0,9,1,2,8,5,0,2,5,3,3};
int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int res=0;
bool str[13][32];
bool check(int x,int y){
if(x>12||x<1) return false;
if(y<=0||y>months[x]) return false;
if(str[x][y]) return false;
str[x][y]=true;
return true;
}
int main(){
for(int i=0;i<41;i++){
if(a[i]>1) continue;
for(int j=i+1;j<41;j++){
for(int z=j+1;z<41;z++){
if(a[z]>3) continue;
for(int k=z+1;k<41;k++){
int mm=a[i]*10+a[j];
int dd=a[z]*10+a[k];
if(check(mm,dd)) res++;
}
}
}
}
printf("%d",res);
return 0;
}
第12届蓝桥杯F试题:日期统计 入口
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
ll n;
int oneM=60;
int oneH=3600;
int oneD=86400;
int main(){
cin>>n;
n/=1000;
n%=oneD;
int HH=n/oneH;
n%=oneH;
int MM=n/oneM;
n%=oneM;
int SS=n;
printf("%02d:%02d:%02d",HH,MM,SS);
return 0;
}