S+20250808测试
A. 沙漠化
暴力BFS即可。
#include<bits/stdc++.h>
using namespace std;
int n,m,t,ans;
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
string a[15];
struct node{
int x,y,id;
};
queue<node> q;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
m=a[1].size();
for(int i=1;i<=n;i++) for(int j=0;j<m;j++)
if(a[i][j]=='D') ans++,q.push({i,j,0});
cin>>t;
if(!ans){
cout<<0;
return 0;
}
if(t>=n*m){
cout<<n*m;
return 0;
}
while(q.size()){
node now=q.front();
q.pop();
int x=now.x,y=now.y,id=now.id;
if(id==t) continue;
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx<1||nx>n||ny<0||ny>=m) continue;
if(a[nx][ny]=='F'){
a[nx][ny]='D';
ans++,q.push({nx,ny,id+1});
}
}
}
cout<<ans;
return 0;
}
C++B. 筒装球
相当于模拟一个包含分别为数字与数字个数两个元素的栈。
#include<bits/stdc++.h>
using namespace std;
int n,x,ans;
struct node{
int a,sum;
};
stack<node> s;
int main(){
cin>>n;
s.push({0,0});
while(n--){
cin>>x;
node now=s.top();
if(now.a==x){
s.pop();
ans-=now.sum;
if(now.sum+1!=x) s.push({x,now.sum+1}),ans+=now.sum+1;
}
else{
s.push({x,1});
ans++;
}
cout<<ans<<endl;
}
return 0;
}
C++C. 双循环锦标赛
暴力DFS,在结尾判断序列是否合法。
判断方式:
用四个变量 $a,b,c,d$ 分别表示胜场为 $n(n-1)$,$n(n-1)-1$,$1$,$0$ 的数量,
若 $a>1$ 或 $d>1$,显然不对,因为全输和全胜只能存在一个。
若 $a=1$ 且 $b=1$ 显然也是不正确的,因为这是双循环赛制,如果有人全胜,不可能存在只输一场的人,对于全败也同理。
最后在循环的时候还要判断与没有出现胜场次数大于 $n(n-1)$ 的,这显然不符合。
所以代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n,m,ans;
int a[N];
void dfs(int x,int y,int sum){
if(x==n){
if(sum==n*(n-1)){
int sum1=0,sum2=0,sum3=0,sum4=0;
for(int i=1;i<=n;i++){
if(a[i]==0) sum1++;
if(a[i]==2*(n-1)) sum2++;
if(a[i]==1) sum3++;
if(a[i]==2*(n-1)-1) sum4++;
if(a[i]>2*(n-1)) return;
}
if((sum1==0||sum1==1&&sum3==0)&&(sum2==0||sum2==1&&sum4==0)){
ans++;
}
}
}
else{
for(int i=0;i<=min(y,n*(n-1)-sum);i++){
a[x+1]=i;
dfs(x+1,i,sum+i);
}
}
}
int main(){
cin>>n>>m;
a[1]=m;
dfs(1,m,m);
cout<<ans;
return 0;
}
C++D. 奶牛求幂
根据题面很容易想到使用迭代加深搜索,
但显而易见是需要一点剪枝的。
可以发现,设当前两个存储器内存储的指数分别为 $a,b$,深度限制为 $dep$,当前深度为 $now$。
首先:无论操作几次,最终都只能得到 $na+mb$,又因为 $gcd(a,b)|na+mb$,所以当 $gcd(a,b)\nmid p$ 时可以直接退出;
其次:当目前最大的数乘上 $2^{dep-now}$ 还是小于 $p$ 时,也直接退出。
所以代码如下:
#include<bits/stdc++.h>
using namespace std;
int p,dep;
int gcd(int x,int y){
if(!y) return x;
else return gcd(y,x%y);
}
bool dfs(int a,int b,int now){
if(a<b) swap(a,b);
if(now==dep) return a==p;
if(a&&b) if(p%gcd(a,b)) return 0;
if(a<<(dep-now)<p) return 0;
if(dfs(a+a,b,now+1)) return 1;
if(dfs(a+a,a,now+1)) return 1;
if(dfs(a,b+b,now+1)) return 1;
if(dfs(b+b,b,now+1)) return 1;
if(dfs(a+b,b,now+1)) return 1;
if(dfs(b+a,a,now+1)) return 1;
if(dfs(b,abs(a-b),now+1)) return 1;
if(dfs(a,abs(a-b),now+1)) return 1;
return 0;
}
int main(){
cin>>p;
while(!dfs(1,0,0)) dep++;
cout<<dep;
return 0;
}
C++E. 方格路径K大和
可以先用 $n^2$ 的复杂度枚举一个点 $(i,j)$,
并以该点为参考,再以 $n^3$ 的复杂度进行dp,
设 $dp_{i,j,k}$ 表示走到点 $(i,j)$ 时选了 $k$ 个大于或等于参考点的最小权值和,
就可以很轻松地想到如下代码中的转移
#include<bits/stdc++.h>
using namespace std;
#define N 35
#define int long long
int n,m,k;
int mp[N][N],dp[N][N][2*N];
int ans=1e18;
signed main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>mp[i][j];
for(int x=1;x<=n;x++) for(int y=1;y<=m;y++){
memset(dp,0x3f,sizeof(dp));
dp[1][0][0]=dp[0][1][0]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]>=mp[x][y])
for(int cnt=1;cnt<=k;cnt++)
dp[i][j][cnt]=min(dp[i][j][cnt],min(dp[i-1][j][cnt-1],dp[i][j-1][cnt-1])+mp[i][j]);
if(mp[i][j]<=mp[x][y])
for(int cnt=0;cnt<=k;cnt++)
dp[i][j][cnt]=min(dp[i][j][cnt],min(dp[i-1][j][cnt],dp[i][j-1][cnt]));
}
ans=min(ans,dp[n][m][k]);
}
}
cout<<ans;
return 0;
}
C++F. 树上字符串匹配
这题可以考虑kmp。
可以发现,建树时将边权改为字符串,
当dfs树的时候,只需保留小字符串的指针就可以。
所以如下代码比较板子:
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
struct node{
int v;
string w;
};
int n,ans,siza;
int next1[N];
string a;
vector<node> t[N];
void get_next(){
next1[0]=-1;
int k=-1;
for(int i=1;i<siza;i++){
while(k>-1&&a[k+1]!=a[i]) k=next1[k];
if(a[k+1]==a[i]) k++;
next1[i]=k;
}
}
void dfs(int u,int idx,int fa){
for(int i=0;i<t[u].size();i++){
int v=t[u][i].v;
string s=t[u][i].w;
if(v==fa) continue;
int j=idx;
for(int k=0;k<s.size();k++){
while(j>-1&&a[j+1]!=s[k]) j=next1[j];
if(a[j+1]==s[k]) j++;
if(j==siza-1){
ans++;
j=next1[j];
}
}
dfs(v,j,u);
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n;
for(int i=2;i<=n;i++){
int u;
string s;
cin>>u>>s;
t[i].push_back({u,s});
t[u].push_back({i,s});
}
cin>>a;
siza=a.size();
if(siza==0){
cout<<0;
return 0;
}
get_next();
dfs(1,-1,0);
cout<<ans;
return 0;
}
C++
Comments NOTHING