睿抗
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
注意点:
- &引用符就是只能指向一个数,后面都是它
- 有多组数据时,初始化要注意。最好都在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;
}
总结
- 模拟题模块化编程,这样不同意出错,思路也能很清晰。
- 不会的题可以想暴力,爆搜是个好方法。
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;
}