这次rank23~又回到紫名啦~
A.枚举插入的位置和插入的字符,暴力判断即可。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
string S;
int s[20],n[20];
int main()
{
cin>>S;
for (int i=0;i<S.length();i++)
s[i+1]=(int)(S[i]-'a'+1);
for (int i=1;i<=S.length()+1;i++)
for (int k=1;k<=26;k++)
{
n[i]=k;
for (int j=1;j<=i-1;j++)
n[j]=s[j];
for (int j=i;j<=S.length();j++)
n[j+1]=s[j];
int l=1,r=S.length()+1;
bool f=false;
while (n[r]==n[l])
{
r--,l++;
if (l>=r)
{
f=true;
break;
}
}
if (f)
{
for (int j=1;j<=S.length()+1;j++)
cout<<(char)('a'+n[j]-1);
cout<<endl;
return 0;
}
}
cout<<"NA"<<endl;
return 0;
}
B.暴力dfs每一种颜色
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
using namespace std;
int tot=0,n,m,h[105],q,de,c[105],v[105];
struct edge
{
int c,y,ne;
}e[10000];
void Add(int x,int y,int c)
{
tot++;
e[tot].y=y;
e[tot].c=c;
e[tot].ne=h[x];
h[x]=tot;
}
void dfs(int x,int now)
{
if (x==de)
{
c[now]=1;
return;
}
for (int i=h[x];i;i=e[i].ne)
{
if (e[i].c!=now) continue;
int y=e[i].y;
if (!v[y])
{
v[y]=1;
dfs(y,now);
v[y]=0;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y,co;
scanf("%d%d%d",&x,&y,&co);
Add(x,y,co);Add(y,x,co);
}
scanf("%d",&q);
while (q--)
{
int x;
scanf("%d%d",&x,&de);
memset(v,0,sizeof(v));
memset(c,0,sizeof(c));
v[x]=1;
for (int i=h[x];i;i=e[i].ne)
{
int y=e[i].y;
v[y]=1;
dfs(y,e[i].c);
v[y]=0;
}
int ans=0;
for (int i=1;i<=m;i++)
ans+=c[i];
cout<<ans<<endl;
}
return 0;
}
C.
这道题显然是个dp,但是暴力的dp超时超空间。
仔细观察可以发现最多只有500种步行的长度,比如d=1,假设每次都增加1,不到250就超过30000了;每次减少一步也同理。
这个时候dp就是500*30000了,可以过的。
注意这道题中说超过30000就不能走!!
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#define M 30005
#include <queue>
using namespace std;
struct data
{
int p,n;
};
int c[M],n,d,f[M][505],b[M],k[M];
int main()
{
int ma=0;
scanf("%d%d",&n,&d);
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
c[x]++;
ma=max(ma,x);
}
if (d<=250)
{
for (int i=1;i<=d+250;i++)
b[i]=i,k[i]=i;
}
else
{
int now=0;
for (int i=d-250;i<=min(30000,d+250);i++)
b[++now]=i,k[i]=now;
}
memset(f,-1,sizeof(f));
f[d][k[d]]=c[d];
int ans=f[d][k[d]];
for (int i=d;i<=min(ma,30000-1);i++)
for (int j=1;j<=500;j++)
{
if (f[i][j]==-1) continue;
int m=b[j];
for (int now=max(m-1,1);now<=m+1;now++)
{
int de=i+now;
if (de>30000) continue;
f[de][k[now]]=max(f[de][k[now]],f[i][j]+c[de]),
ans=max(ans,f[de][k[now]]);
}
}
cout<<ans<<endl;
return 0;
}
考试A了前三个。。
D题看题解明白了:
找每一个连通的块,设块中有x个点。
如果其中没有环,那么这个块要建x-1条边就可以保证全部满足,因为没有环的话,就一定可以拓扑排序,那么把拓扑排序之后的点连成一条链,就可以满足要求。
如果有环的话就要x条边了。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int v[200005],h2[200005],in[200005],h[200005],tot=0,k,n,m;
struct edge
{
int y,ne;
}e[400005];
queue<int> q;
void Add(int x,int y)
{
tot++;
e[tot].y=y;
e[tot].ne=h[x];
h[x]=tot;
}
void Add2(int x,int y)
{
tot++;
e[tot].y=y;
e[tot].ne=h2[x];
h2[x]=tot;
}
void dfs(int x)
{
if (!in[x]) q.push(x);
tot++;
v[x]=1;
for (int i=h2[x];i;i=e[i].ne)
{
int y=e[i].y;
if (v[y]) continue;
dfs(y);
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Add(x,y);
Add2(x,y);Add2(y,x);
in[y]++;
}
int ans=0;
for (int i=1;i<=n;i++)
if (!v[i])
{
tot=0;
k=0;
while (!q.empty())
q.pop();
dfs(i);
if (tot==1) continue;
int ok=0;
while (!q.empty())
{
int x=q.front();
q.pop();
ok++;
if (ok>tot) break;
for (int i=h[x];i;i=e[i].ne)
{
in[e[i].y]--;
if (!in[e[i].y]) q.push(e[i].y);
}
}
if (ok==tot) ans+=(tot-1);
else ans+=tot;
}
cout<<ans<<endl;
return 0;
}