B题题意,在一个n*m的宫殿里,公主要逃出宫殿,出口位置用%表示,@表示公主位置,$表示士兵,#表示墙,. 表示
空地,士兵和公主都可以在单位时间内向相邻的格子走一步,如果公主和士兵走到了一个格子甚至是出口位置,那么公主就会被抓住,问公主能否成功逃出宫殿
这个题计算公主到达出口的时间是否小于任何一个士兵到达出口的时间就好了,但是由于士兵多,出口唯一,所以我们以出口为起点进行搜索,算出出口达到最近的士兵的距离,以及到达公主的距离,比较输出就好了
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
const int maxn=1000,inf=0x3f3f3f3f;
struct node
{
int x,y,d;
node()
{
;
}
node (int a,int b,int c)
{
x=a;
y=b;
d=c;
}
};
int n,m;
int vis[maxn][maxn];
char str[maxn][maxn];
int dx[4]= {1,0,-1,0};
int dy[4]= {0,1,0,-1};
int bfs(node start,char endC)
{
if(start.x==-1)
return inf;
memset(vis,0,sizeof(vis));
vis[start.x][start.y]=1;
queue<node>que;
que.push(start);
while(!que.empty())
{
node now=que.front();
que.pop();
if(str[now.x][now.y]==endC)
return now.d;
int nx,ny;
for(int i=0; i<4; i++)
{
nx=dx[i]+now.x;
ny=dy[i]+now.y;
if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&(str[nx][ny]=='.'||str[nx][ny]==endC))
{
que.push(node(nx,ny,now.d+1));
vis[nx][ny]=1;
}
}
}
return inf;
}
int main()
{
while(scanf("%d%d",&n,&m)!=-1)
{
for(int i=0; i<n; i++)
scanf("%s",str[i]);
node start;
int flag=0;
start.x=-1;
start.y=-1;
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(str[i][j]=='%')
{
start.x=i;
start.y=j;
start.d=0;
}
}
}
int d1=bfs(start,'@');
int d2=bfs(start,'$');
if(d1<d2)
puts("Yes");
else
puts("No");
}
return 0;
}
E题,一棵有根树,在这棵树上两个子树similar 的条件是 :两个子树节上点深度相同节点个数相同,问有多少对这样的子树,子树定义是:以某个节点为根,该节点以及该节点以下的全部节点组成的树为一颗子树;
我的初始想法是找出 以每个节点为根 ,下面每层的节点个数,保存到一个串中,把每个节点的串作为key值放到map数组中,每个串的个数=k ans= sum(C(2,k)),C 为组合数
举例
5
1 2
1 3
2 4
2 5
那么1=“122” , 2=“12” , 3=“1” , 4=“1” , 5=“1” ,但是这样做超内存了,后来学习了大神的哈希存储法,
设质数p,从底层推, h5=1,h4=1,h3=1 ,h2=h2+p*(h4+h5)=2p+1,h1=h1+p*(h2+h3 )=2p^2+p+1,如果i j 两节点哈希值相等,即意味着以 i j 为根的子树每一层节点个数都相同,然后利用哈希值映射到map数组,计算组合数即可,
看一下我的字符串代码~:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#include <map>
#include <string>
#include <sstream>
#include <set>
using namespace std;
typedef long long LL;
const LL maxn=1e6+10;
vector<LL>G[maxn];
vector<LL>son[maxn];
vector<LL>temp[maxn];
map<string,LL>mp;
map<string,LL>::iterator it_map;
void add(LL u,LL v)
{
if(son[u].size()==1)
{
for(int i=0; i<son[v].size(); i++)
son[u].push_back(son[v][i]);
return;
}
temp[u].clear();
temp[u].push_back(1);
LL x,y;
for(int i=1,j=0; (i<son[u].size()||j<son[v].size()); i++,j++)
{
if(i<son[u].size())
x=son[u][i];
else x=0;
if(j<son[v].size())
y=son[v][j];
else y=0;
temp[u].push_back(x+y);
}
son[u].clear();
for(int i=0; i<temp[u].size(); i++)
son[u].push_back(temp[u][i]);
}
void dfs(LL u,LL pre)
{
son[u].push_back(1);
for(LL i=0; i<G[u].size(); i++)
{
LL v=G[u][i];
if(v==pre)
continue;
dfs(v,u);
add(u,v);
}
}
int main()
{
//
LL n;
LL u,v;
while(scanf("%lld",&n)!=-1)
{
for(LL i=0; i<=n; i++)
{
G[i].clear();
son[i].clear();
temp[i].clear();
}
mp.clear();
for(LL i=1; i<n; i++)
{
scanf("%lld%lld",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0);
for(LL i=1; i<=n; i++)
{
string temp="";
for(LL j=0; j<son[i].size(); j++)
{
stringstream ss;
ss<<son[i][j];
temp+=(ss.str()+"#");///区分层与层之间的节点个数
}
mp[temp]++;
}
LL ans=0;
for(it_map=mp.begin(); it_map!=mp.end(); it_map++)
{
ans=ans+((it_map->second-1)*it_map->second)/2;
}
printf("%lld\n",ans);
}
return 0;
}
下面是哈希 代码,当然AC了
:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const LL maxn=1e6+10,p=9901,mod=1e9+7;
vector<LL>G[maxn];
LL hash_v[maxn];
map<LL,LL>mp;
map<LL,LL>::iterator it;
void dfs(LL u)
{
hash_v[u]=1;
for(LL i=0; i<G[u].size(); i++)
{
LL v=G[u][i];
dfs(v);
hash_v[u]=(hash_v[u]+hash_v[v]*p)%mod;
}
mp[hash_v[u]]++;
}
int main()
{
///freopen("in.txt","r",stdin);
LL n;
LL u,v;
while(scanf("%lld",&n)!=-1)
{
for(LL i=0; i<=n; i++)
G[i].clear();
mp.clear();
for(LL i=1; i<n; i++)
{
scanf("%lld%lld",&u,&v);
G[u].push_back(v);
}
dfs(1);
LL ans=0;
for(it=mp.begin(); it!=mp.end(); it++)
ans+=it->second*(it->second-1)/2;
printf("%lld\n",ans);
}
return 0;
}