睿抗题解集

2022国赛

RC-u1 智能红绿灯

在这里插入图片描述

模拟题:注意细节

#include<bits/stdc++.h>
using namespace std;
//#define int long long 
#define x first
#define y second 
typedef pair<int,int> pii;

const int N=1e6+10;
int a[N];
pii ans[N];
int cnt=0;

void solve(){
	int n;cin>>n;
	for(int i=0;i<n;i++) cin>>a[i];
	int flag=0,st=a[0]+15,ed=st+29;
	for(int i=1;i<n;i++){
		if(st<=a[i]&&a[i]<=ed){
			if(!flag){
				flag=1;
				ed=ed+15;
			}
		}else{
			if(a[i]>ed){
				flag=0;
				ans[cnt++]={st,ed};
				st=a[i]+15;
				ed=st+29;
			}
		}
	}
	ans[cnt++]={st,ed};
	for(int i=0;i<cnt;i++){
		cout<<ans[i].x<<" "<<ans[i].y<<endl;
	}
	return ;
}

signed main(){
	int T=1;
//	cin>>T;
	while(T--){
		solve();
	}
	return 0;
} 

RC-u2 女王的大敕令

题目链接

模拟题:直接枚举两个坐标,然后用曼哈顿距离和题意攻击范围来判断是否合法。
曼哈顿距离=abs(x1-x2)+abs(y1-y2)

  • 法一 用的dfs(自己当时写的时候有点蠢)
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define x first
#define y second
typedef pair<int,int> pii;

const int N=1e6+10;
struct info {
	int sx,sy,lx,ly;
	bool operator<(const info& W) const {
		if(sx==W.sx&&sy==W.sy&&lx==W.lx) return ly<W.ly;
		if(sx==W.sx&&sy==W.sy) return lx<W.lx;
		if(sx==W.sx) return sy<W.sy;
		return sx<W.sx;
	}
} ans[N];
int c1,c2,r1,r2,n1,n2,n3,n4,fx,fy,d1,d2;
int st1[6][6],st2[6][6];
int cnt=0;

void dfs1(int x,int y) {
	for(int i=-d1; i<=d1; i++) {
		int j=d1-abs(i);
		for(int k=-1; k<2; k++) {
			if(k==0) continue;
			int tx=x+i,ty=y+k*j;
			if(tx<1||tx>5||ty<1||ty>5) continue;
			if(st2[tx][ty]) continue;
//			cout<<"... "<<tx<<" "<<ty<<endl;
			ans[cnt++]= {tx,ty,x,y};
			if(j==0) break;
		}
	}
}
void dfs(int x,int y) {
	for(int i=-d2; i<=d2; i++) {
		int j=d2-abs(i);
		for(int k=-1; k<2; k++) {
			if(k==0) continue;
			int tx=x+i,ty=y+k*j;
			if(tx<1||tx>5||ty<1||ty>5) continue;
			if(st1[tx][ty]) continue;
//			cout<<"--- "<<tx<<" "<<ty<<endl;
			dfs1(tx,ty);
			if(j==0) break;
		}
	}
}
void solve() {
	cin>>c1>>c2>>r1>>r2>>n1>>n2>>n3>>n4>>fx>>fy>>d1>>d2;
	for(int i=1; i<6; i++) {
		st1[r1-n3][i]=st1[r2+n4][i]=st1[i][c1+n1]=st1[i][c2-n2]=true;
		st2[r1-n3][i]=st2[r2+n4][i]=st2[i][c1]=st2[i][c2]=true;
	}
	dfs(fx,fy);
	sort(ans,ans+cnt);
	for(int i=0; i<cnt; i++) {
		cout<<ans[i].sx<<" "<<ans[i].sy<<" "<<ans[i].lx<<" "<<ans[i].ly<<endl;
	}
}

signed main() {
	int T=1;
//	cin>>T;
	while(T--) {
		solve();
	}
	return 0;
}
  • 法二:直接枚举两个坐标,四重循环
//AC
#include <bits/stdc++.h>

using namespace std;
const int N = 1e5;
int mp[6][6], mp2[6][6];
int c1, c2, r1, r2;
int n[5];
int r, c, d1, d2;
int idx;

struct node
{
	int x, y, x2, y2;
}no[N];

bool cmp(node x, node y)
{
	if(x.x == y.x && x.y == y.y && x.x2 == y.x2) return x.y2 < y.y2;
	else if(x.x == y.x && x.y == y.y) return x.x2 < y.x2;
	else if(x.x == y.x) return x.y < y.y;
	else return x.x < y.x;
}

int main()
{
	cin >> c1 >> c2 >> r1 >> r2;
	for(int i = 1;i <= 4;i ++) cin >> n[i];
	cin >> r >> c >> d1 >> d2;
	// 左右两侧怪物移动后的激光覆盖情况 
	for(int i = 1;i <= 5;i ++)
	{
		mp[i][c1] = 1;
		mp[i][c2] = 1;
		mp[r1-n[3]][i] = 1;
		mp[r2+n[4]][i] = 1;
	}
	// 上下两侧怪物移动后的激光覆盖情况
	for(int i = 1;i <= 5;i ++)
	{
		mp2[i][c1+n[1]] = 1;
		mp2[i][c2-n[2]] = 1;
		mp2[r1-n[3]][i] = 1;
		mp2[r2+n[4]][i] = 1;
	} 
	// 枚举两个位置
	for(int i = 1;i <= 5;i ++)
	{
		for(int j = 1;j <= 5;j ++)
		{
			if(!mp[i][j]) 
			{
				for(int i1 = 1;i1 <= 5;i1 ++)
				{
					for(int j1 = 1;j1 <= 5;j1 ++)
					{
						if(!mp2[i1][j1])
						{
							// 判断曼哈顿距离
							int dd2 = abs(r-i1) + abs(c-j1);
							int dd1 = abs(i1-i) + abs(j1-j);
							if(dd2 == d2 && dd1 == d1)
							{
								no[idx].x = i;
								no[idx].y = j;
								no[idx].x2 = i1;
								no[idx].y2 = j1;
								idx ++;
							}
						}
					}
				}
			}
		}
	}
	// 排序输出
	sort(no, no+idx, cmp);
	for(int i = 0;i < idx;i ++)
	{
		cout << no[i].x << ' ' << no[i].y << ' ';
		cout << no[i].x2 << ' ' << no[i].y2 << endl;
	}
	return 0;
}

RC-u3 战利品分配

这里是引用

- 思路:经典的最短路模型加维护题目要求变量

  • 法一:dj
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N=2e5+10;
typedef pair<int,int> pii;
int d[N],w[N],f[N],st[N];
int h[N],e[N],ne[N],idx;
int n,m,k,p;
int S,T;

void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dj(){
	memset(d,0x3f,sizeof d);
	d[S]=0;
	if(d[S]%k==p) f[S]=w[S];
	else f[S]=0;
	priority_queue<pii,vector<pii>,greater<pii>> q;
	q.push({0,S});
	while(q.size()){
		auto t=q.top();
		q.pop();
		int ver=t.y;
		if(st[ver]) continue;
		st[ver]=true;
		for(int i=h[ver];~i;i=ne[i]){
			int j=e[i];
			if(d[j]>d[ver]+1){
				d[j]=d[ver]+1;
				q.push({d[j],j});
				f[j]=max(f[j],f[ver]+((d[j]%k==p)?w[j]:0));
			}else if(d[j]==d[ver]+1){
				f[j]=max(f[j],f[ver]+((d[j]%k==p)?w[j]:0));
			}
		}
	} 
}

void solve(){
	memset(h,-1,sizeof h);
	cin>>n>>m>>k>>p;
	p--;
	for(int i=1;i<=n;i++) cin>>w[i];
	while(m--){
		int u,v;
		cin>>u>>v;
		add(u,v),add(v,u);
	}
	cin>>S>>T;
	dj();
	cout<<f[T]<<endl;
}


signed main(){
	int t=1;
	while(t--){
		solve();
	}
	return 0;
}
  • 法二:BFS
//3, bfs, AC
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int maxn = 1e5+10, inf = 1e9+7;

int n, m, k, p, w[maxn], st, ed, ans;

//bfs找最短路(维护当前获得的价值)
vector<int>G[maxn];
int vis[maxn];
struct node{ int u, step, val; };
void bfs(){
    queue<node>q;
    if(p==1)q.push({st, 0, w[st]});  //p==1可以多拿到一个起点的价值
    else q.push({st, 0, 0});
    vis[st] = 1;
    p--;  //方便后面计算
    int res = inf;
    while(q.size()){
        int u = q.front().u, v = q.front().val, dd = q.front().step;  q.pop();
        if(dd > res)break;
        if(u==ed){
            res = dd;
            ans = max(ans, v);
            continue;
        }
        for(int to : G[u]){
            if(vis[to] && to!=ed)continue;
            vis[to] = 1;
            if((dd+1)%k == p)q.push({to, dd+1, v+w[to]});
            else q.push({to, dd+1, v});
        }
    }
}

int main(){
    cin>>n>>m>>k>>p;
    for(int i = 1; i <= n; i++)cin>>w[i];
    for(int i = 1; i <= m; i++){
        int u,v ;  cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    cin>>st>>ed;
    bfs();
    cout<<ans<<"\n";
    return 0;
}

RC-u4 变牛的最快方法

这里是引用

思路:DP—编辑距离+求状态转移的路径

#include<bits/stdc++.h>
using namespace std;
//#define int long long 
#define x first
#define y second 
typedef pair<int,int> pii;

const int N=1e3+10;
int f[N][N],op[N][N];
pii pre[N][N];
int n,m;
int a[N],b[N];

void init(){
	for(int i=0;i<=n;i++){
		f[i][0]=i;
		op[i][0]=0;
		pre[i][0]={i-1,0};
	}
	for(int i=0;i<=m;i++){
		f[0][i]=i;
		op[0][i]=3;
		pre[0][i]={0,i-1};
	}
}
void solve(){
	int x;
	while(cin>>x){
		a[++n]=x;
		if(x==-1) break;		
	}
	while(cin>>x){
		b[++m]=x;
		if(x==-1) break; 
	}
	init();
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			int t0,t1,t2,t3,flag=1;
			t0=f[i-1][j]+1;
			t3=f[i][j-1]+1;
			if(a[i]==b[j]) flag=0;
			t1=f[i-1][j-1]+flag;
			f[i][j]=min(t0,min(t1,t3));
			auto &t=f[i][j];
			if(t==t0){
				op[i][j]=0;
				pre[i][j]={i-1,j};
			}else if(t==t3){
				op[i][j]=3;
				pre[i][j]={i,j-1};
			}else{
				if(flag){
					op[i][j]=1;
					pre[i][j]={i-1,j-1};
				}else{
					op[i][j]=2;
					pre[i][j]={i-1,j-1};
				}
			}
		}
	}
	
	cout<<f[n][m]<<endl;
	pii p=pre[n][m];//处理dp的路径问题常用套路,是背包问题的路径问题的扩展 
	vector<int> ve;
	ve.push_back(op[n][m]);
	while(p.x||p.y){
		int i=p.x,j=p.y;
		ve.push_back(op[i][j]);
		p=pre[i][j];
	}
	reverse(ve.begin(),ve.end());
	for(auto t:ve) cout<<t;
	return;
}

signed main(){
	int T=1;
//	cin>>T;
	while(T--){
		solve();
	}
	return 0;
} 

RC-u5 养老社区

这里是引用

  • 思路:最短距离,直接用BFS来求,跑n遍BFS维护每个点到所有点的最短距离,再枚举三个点,以最短距离和种类作为合法条件。

  • BFS的时间复杂度为O(N+V)

#include<bits/stdc++.h>
using namespace std;
//#define int long long 
#define x first
#define y second 
typedef pair<int,int> pii;

const int N=4e3+10;
int kds[N],st[N];
int d[N][N];
int h[N],e[N],ne[N],idx;
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs(int s){
	d[s][s]=0;
	queue<int> q;
	q.push(s);
	st[s]=true;
	while(q.size()){
		auto t=q.front();
		q.pop();
		for(int i=h[t];~i;i=ne[i]){
			int j=e[i];
			if(st[j]) continue;
			st[j]=true;
			q.push(j);
			d[s][j]=d[s][t]+1;
		}
	}
}
void solve(){
	memset(h,-1,sizeof h);
	int n;cin>>n;
	memset(d,0x3f,sizeof d);
	for(int i=0;i<n-1;i++){
		int u,v;cin>>u>>v;
		add(u,v),add(v,u);
	}
	for(int i=1;i<=n;i++){
		cin>>kds[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			st[j]=0;
		bfs(i);
	}
	
	int cnt=0;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			for(int k=j+1;k<=n;k++){
				if(d[i][j]==d[i][k]&&d[i][j]==d[j][k]){
					if(kds[i]!=kds[j]&&kds[i]!=kds[k]&&kds[j]!=kds[k]){
						cnt++;
					}
				}
			}
		}
	}
	cout<<cnt;
}

signed main(){
	int T=1;
//	cin>>T;
	while(T--){
		solve();
	}
	return 0;
} 

2023国赛

RC-u1 睿抗,启动!

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
char a[26],b[26];
string s;

int change(int op,int idx){
    if(op==1){
        for(int i=idx;i<s.size();i++){
            if(!isupper(s[i])) return i-1;
            if(i==s.size()-1) return i;
        }
    }
    else if(op==0){
        for(int i=idx;i<s.size();i++){
            if(!islower(s[i])) return i-1;
            if(i==s.size()-1) return i;
        }
    }
}
signed main(){
	int n;
	cin>>n>>s;
    if(s=="yourname") s="xxxxxx";
	cout<<s<<endl;
	for(int i=0;i<26;i++){
		a[i]='a'+i;
		b[i]='A'+i;
	}
	while(n--){
		for(int i=0;i<s.size();i++){
            if(isdigit(s[i])) continue;
			if(isupper(s[i])){
				s[i]=b[(s[i]-'A'+1)%26];
			}else
				s[i]=a[(s[i]-'a'-1+26)%26];
            // cout<<"- "<<s[i]<<endl;
		}
		// cout<<s<<endl;
		for(int i=0;i<s.size();i++){
            if(isdigit(s[i])) continue;
            int j;
            if(isupper(s[i])){
                j=change(1,i);
                // cout<<"---- "<<j<<endl;
                if(j-i+1>=3){
                    for(int l=i;l<=j;l++) s[l]=tolower(s[l]);
                }
            }else{
                j=change(0,i);
                 if(j-i+1>=3){
                    for(int l=i;l<=j;l++) s[l]=toupper(s[l]);
                }
            }
            i=j;
		}
	}
	cout<<s<<endl;
}

RC-u2 桌游猜谜

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
const int N=10;
int st[N][N],arr[N][N];
typedef pair<int,int> pii;
pii ans,temp;

//选的三种颜色为x1,x2,x3,区间为[l,r],cnt表示当前在选择第Xi个颜色的数,sum为所选数的总和(选三个数) 
void dfs(int x1,int x2,int x3,int l,int r,int cnt,int sum){
	if(cnt>=4){
		if(sum>=l&&sum<=r) temp.x++;
		else temp.y++;
		return;
	}
	int t;
	if(cnt==1) t=x1;
	else if(cnt==2) t=x2;
	else t=x3;
	
	for(int i=1;i<=8;i++){
		if(!st[t][i]){
			st[t][i]=true;
			dfs(x1,x2,x3,l,r,cnt+1,sum+i);
			st[t][i]=false;
		}
	}
}

void check(int x1,int x2,int x3,int l,int r){
	temp={0,0};
	dfs(x1,x2,x3,l,r,1,0);
	if(min(temp.x,temp.y)>min(ans.x,ans.y)){
		ans=temp;
	}
}

void solve(){
	int n;
	cin>>n;
	memset(st,0,sizeof st);
	memset(arr,0,sizeof arr);
	ans={-1,-1};
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=6;j++){
			cin>>arr[i][j];
			st[j][arr[i][j]]=true;//标记第j种颜色中的哪个数被选了 
		}
	}
	
	for(int i=1;i<=6;i++){
		for(int j=i+1;j<=6;j++){
			for(int k=j+1;k<=6;k++){
				for(int l=3;l<=24;l++){
					for(int r=l;r<=24;r++){
						check(i,j,k,l,r);
					}
				}
			}
		}
	}
	int t=max(ans.x,ans.y);//求最大的可能方案 
	cout<<t*pow(8-n,3)<<endl;
}

signed main(){
	int T=1;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

RC-u3 兰州拉面派餐系统

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
const int N=1e5+10;
int kinds[N],kd[N];
vector<pii> ans;//存放结束时间和客单号
int num[N];//篮子使用的次数 
 
struct info{
	int et,kid,lid;//结束时间,客单号,篮子编号
	bool operator<(const info& W) const{
		return et>W.et;
	} 
};

void solve(){
	int n,m,l;
	cin>>n>>m>>l;//面,篮子,客单
	for(int i=1;i<=n;i++) cin>>kinds[i];
	for(int i=1;i<=l;i++) cin>>kd[i];
	
	priority_queue<int,vector<int>,greater<int> > rot;
	priority_queue<info> q;//在处理的订单,堆头为结束时间最小的订单 
	for(int i=1;i<=m;i++) rot.push(i);//可用的篮子 
	
	int cnt=1,times=0;//将要处理的客单号,时间单位 
	while(cnt<=l || q.size()){
		//在处理的订单不空,并且当前订单完成时间等于times时,则把订单弹出,表示订单完成 
		while(q.size()&&q.top().et==times){
			ans.push_back({q.top().et,q.top().kid});
			num[q.top().lid]++;
			rot.push(q.top().lid); 
			q.pop();
		}
		//订单还没处理完,并且有空篮子,将订单放入空蓝子处理 
		while(cnt<=l&&rot.size()){
			q.push({times+kinds[kd[cnt]],cnt++,rot.top()});
			rot.pop();
		}
		times++;
	}
	sort(ans.begin(),ans.end());
	
	for(int i=0;i<ans.size();i++){
		cout<<ans[i].y<<":"<<ans[i].x;
		if(i!=ans.size()-1) cout<<" ";
	}
	cout<<endl;
	for(int i=1;i<=m;i++){
		cout<<num[i];
		if(i!=m) cout<<" ";
	}
	return ;
}


signed main(){
	int T=1;
//	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

RC-u4 拆积木

在这里插入图片描述

  • 法一:容易内存超限
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10,M=1e6+10;
int g[2][N];//需要用滚动数组,不然内存会超限 
int h[M],e[M],ne[M],idx;
short int din[M];

void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void solve(){
	memset(h,-1,sizeof h);
	int n,m;cin>>n>>m;
	unordered_set<int> s;
	s.clear();
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			int x;cin>>x;
			g[i&1][j]=x;
			s.insert(x);
			if(i!=0&&g[i&1][j]!=g[i-1&1][j]){
				add(g[i-1&1][j],g[i&1][j]);
				din[x]++;
			}
		}
	}
	priority_queue<int,vector<int>,greater<int>> q;
	for(int t:s){
		if(din[t]==0){
			q.push(t);
		}
	}
	int cnt=0,tot=s.size();
	if(q.size()==0){
		cout<<"Impossible"<<endl;
		return;
	}
	while(q.size()){
		auto t=q.top();
		q.pop();
		if(cnt!=0) cout<<" ";
		cout<<t;
		cnt++;
		for(int i=h[t];~i;i=ne[i]){
			int j=e[i];
			if(--din[j]==0){
				q.push(j);
			}
		}
	}
	if(cnt!=tot){
		cout<<" "<<"Impossible";
		return;
	}
}

signed main(){
	int T=1;
//	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}
  • 法二:将积木编号一一映射到0到cnt
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10,M=1e6+10;
//#define int long long
#define x first
#define y second
int mp[M],ump[M];
int g[N][N];
int h[M],ne[M],e[M],idx;
int din[M];

void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
struct cmp{
	bool operator()(int a,int b) const{
		return ump[a]>ump[b];
	}
};
void solve(){
	int n,m;cin>>n>>m;
	int cnt=0;
	memset(mp,-1,sizeof mp);
	memset(h,-1,sizeof h);

	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>g[i][j];
			if(mp[g[i][j]]==-1){
				mp[g[i][j]]=cnt++;
			}
			if(i!=1&&mp[g[i-1][j]]!=mp[g[i][j]]){
				add(mp[g[i-1][j]],mp[g[i][j]]);
				din[mp[g[i][j]]]++;
			}
		}
	}
	
	for(int i=1;i<=1e6;i++){
		if(mp[i]!=-1){
			ump[mp[i]]=i;
		}
	}

	priority_queue<int,vector<int>,cmp> q;
	for(int i=0;i<cnt;i++){
		if(din[i]==0){
			q.push(i);
		}
	}

	if(q.size()==0){
		cout<<"Impossible";
		return;
	}
	int num=0;
	while(q.size()){
		auto t=q.top();
		q.pop();
		if(num!=0) cout<<" ";
		cout<<ump[t];
		num++;
		for(int i=h[t];~i;i=ne[i]){
			int j=e[i];
			if(--din[j]==0){
				q.push(j);
			}
		} 
	}
	if(num!=cnt){
		cout<<" "<<"Impossible";
		return;
	}
}

signed main(){
	int T=1;
//	cin>>T;//这里不注释,debug到你疯 
	while(T--){
		solve();
	}
	return 0;
}

RC-u5 栈与数组

在这里插入图片描述

  • 法一:DFS(17分)
#include<bits/stdc++.h>
using namespace std;
// #define int long long
#define x first
#define y first
const int N=1e3+5,M=2e3+5;
int n,m,k;
int st[M];
int a[N],b[N];
int ans;

void dfs(int pn,int pm,int cnt,int sum) {
    if(sum>=ans) return;
	if(pn>=n&&pm>=m) {
		ans=min(ans,sum);
		return;
	}
	if(pn>=n) {
		if(st[b[pm]]+1>=k) {
			st[b[pm]]-=(k-1);
			if(cnt<sum) {
				dfs(pn,pm+1,cnt+1-k,sum);
			} else {
				dfs(pn,pm+1,cnt+1-k,sum+1);
			}
			st[b[pm]]+=(k-1);
		} else {
			st[b[pm]]++;
			if(cnt<sum) {
				dfs(pn,pm+1,cnt+1,sum);
			} else dfs(pn,pm+1,cnt+1,sum+1);
			st[b[pm]]--;
		}
		return;
	}
	if(pm>=m) {
		if(st[a[pn]]+1>=k) {
			st[a[pn]]-=(k-1);
			if(cnt<sum) {
				dfs(pn+1,pm,cnt+1-k,sum);
			} else {
				dfs(pn+1,pm,cnt+1-k,sum+1);
			}
			st[a[pm]]+=(k-1);
		} else {
			st[a[pn]]++;
			if(cnt<sum) {
				dfs(pn+1,pm,cnt+1,sum);
			} else dfs(pn+1,pm,cnt+1,sum+1);
			st[a[pn]]--;
		}
		return;
	}
	if(st[a[pn]]+1>=k) {
		st[a[pn]]-=(k-1);
		if(cnt<sum) {
			dfs(pn+1,pm,cnt+1-k,sum);
		} else {
			dfs(pn+1,pm,cnt+1-k,sum+1);
		}
		st[a[pm]]+=(k-1);
	} else {
		st[a[pn]]++;
		if(cnt<sum) {
			dfs(pn+1,pm,cnt+1,sum);
		} else dfs(pn+1,pm,cnt+1,sum+1);
		st[a[pn]]--;
	}


	if(st[b[pm]]+1>=k) {
		st[b[pm]]-=(k-1);
		if(cnt<sum) {
			dfs(pn,pm+1,cnt+1-k,sum);
		} else {
			dfs(pn,pm+1,cnt+1-k,sum+1);
		}
		st[b[pm]]+=(k-1);
	} else {
		st[b[pm]]++;
		if(cnt<sum) {
			dfs(pn,pm+1,cnt+1,sum);
		} else dfs(pn,pm+1,cnt+1,sum+1);
		st[b[pm]]--;
	}

}
void solve() {
	cin>>n>>m>>k;
	memset(st,0,sizeof st);
	for(int i=0; i<n; i++) cin>>a[i];
	for(int i=0; i<m; i++) cin>>b[i];
	ans=n+m;
	dfs(0,0,0,0);
	cout<<ans<<endl;
}

signed main() {
	int T=1;
	cin>>T;
	while(T--) {
		solve();
	}
	return 0;
}
  • 法二:DP

注意点:

  1. &引用符就是只能指向一个数,后面都是它
  2. 有多组数据时,初始化要注意。最好都在solve里面能设置局部变量就设置局部变量。
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N=2e3+5,inf=0x3f3f3f3f;
typedef pair<int,int> pii;
int a[N],b[N],pa[N];

pii f[N][N];//first为前i个,前j个目前使用个数,second为最大容量 

void solve(){
	int n,m,k;
	cin>>n>>m>>k;
	memset(pa,0,sizeof pa); 
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++) cin>>b[i];
	if(k==1){
		cout<<1<<endl;
		return;
	}
	memset(f,0x3f,sizeof f);
//	vector<vector<pair<int,int>> > f(n + 1, vector<pair<int,int>>(m + 1, {inf, inf}));
	f[0][1]=f[1][0]={1,1};
	for(int i=1;i<=n;i++){
		pa[a[i]]++;
		unordered_map<int,int> mp;
		for(int j=1;j<=m;j++){
			mp[b[j]]++;
			pii u={inf,inf},v={inf,inf};
			auto &t=f[i-1][j];
			//f[i-1][j]->f[i][j]
			if(t.x==t.y) u.y=t.y+1;//最大容量+1 
			else u.y=t.y;
			if((pa[a[i]]+mp[a[i]])%k==0){
				u.x=t.x+1-k;//目前使用的个数 
			}else u.x=t.x+1;
			
			//f[i][j-1]->f[i][j]
			t=f[i][j-1];
			if(t.x==t.y)  v.y=t.y+1;
			else v.y=t.y;
			
			if((pa[b[j]]+mp[b[j]])%k==0){
				v.x=t.x+1-k;
			}else v.x=t.x+1;
			
//			t=f[i][j];//这里赋值不了了,好像指针失效了,这里t好像只是充当一个临时变量,一直是指向f[i-1][j]的,后面只是一直改变f[i-1][j]的值 
			auto &p=f[i][j];
			if(u.y<v.y){
//				f[i][j]=u;
				p=u;
			}else{
//				f[i][j]=v;
				p=v;
			}
		} 
	} 
	cout<<f[n][m].y<<endl;
}

signed main(){
	int T=1;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

总结

  1. 模拟题模块化编程,这样不同意出错,思路也能很清晰。
  2. 不会的题可以想暴力,爆搜是个好方法。

2024省赛

RC-u4 章鱼图的判断

在这里插入图片描述

  • 无向图中,一个环会遍历两次。
  • 法一:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;

int h[N],e[N],ne[N],idx=2;
int tot,num,f,ans;
int st[N],d[N];
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u,int from){
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(!st[j]){
			d[j]=d[u]+1;
			st[j]=true;
			dfs(j,i);
		}else if(i!=(from^1)){
			tot=abs(d[u]-d[j])+1;
			f++;
		}
	}
}

void solve(){
	num=tot=0;
	int n,m;cin>>n>>m;
	memset(h,-1,sizeof h);
	memset(st,0,sizeof st);
	memset(d,0,sizeof d);
	idx=2;
	while(m--){
		int a,b;cin>>a>>b;
		add(a,b),add(b,a);
	}
	for(int i=1;i<=n;i++){
		if(st[i]==0){
			f=tot=0;
			st[i]=true;
			dfs(i,0);
			f/=2;//无向图,一个环有两个圈圈 
			if(f==1){
				num++;
				ans=tot;
			}
		}
	}
	if(num!=1){
		cout<<"No"<<" "<<num<<endl;
		return;
	}else{
		cout<<"Yes"<<" "<<ans<<endl;
		return;
	}
}

signed main(){
	int T;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}
  • 法二
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;

int h[N],e[N],ne[N],idx=2;
int tot,num,f,ans;
int st[N],d[N];
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u,int fa){
	st[u]=true;
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==fa) continue;
		if(!st[j]){
			d[j]=d[u]+1;
			dfs(j,u);
		}else{
			tot=abs(d[u]-d[j])+1;
			f++;
		}
	}
}

void solve(){
	num=tot=0;
	int n,m;cin>>n>>m;
	memset(h,-1,sizeof h);
	memset(st,0,sizeof st);
	memset(d,0,sizeof d);
	idx=2;
	while(m--){
		int a,b;cin>>a>>b;
		add(a,b),add(b,a);
	}
	for(int i=1;i<=n;i++){
		if(st[i]==0){
			f=tot=0;
			dfs(i,-1);
			f/=2;//重点!!! 
			if(f==1){
				num++;
				ans=tot;
			}
		}
	}
	if(num!=1){
		cout<<"No"<<" "<<num<<endl;
		return;
	}else{
		cout<<"Yes"<<" "<<ans<<endl;
		return;
	}
}

signed main(){
	int T;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

RC-u5 工作安排

在这里插入图片描述

  • f [ i ] [ j ] f[i][j] f[i][j]表示前i个任务中,时间恰好为j时,所获得的最大报酬。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
const int N=5e3+10,m=5e3;
int f[N];
struct info{
	int t,d,p;
	bool operator<(const info& W) const{
		return d<W.d;
	}
}a[N];
void solve(){
	int mx=0;
	memset(f,0,sizeof f);
	int n;cin>>n;
	for(int i=0;i<n;i++){
		int t,d,p;
		cin>>t>>d>>p;
		a[i]={t,d,p};
	}
	sort(a,a+n);
	for(int i=0;i<n;i++){
		for(int j=m;j>=0;j--){
			if(j<=a[i].d&&j-a[i].t>=0)//j<=a[i].d是恰好
			f[j]=max(f[j],f[j-a[i].t]+a[i].p);
			mx=max(mx,f[j]);
		}
	}
	cout<<mx<<endl;
}

signed main(){
	int T=1;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
} 
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值