2019年天梯赛补题

题目详情 - L1-064 估值一亿的AI核心代码 (pintia.cn)

思路:

  1. 先对原始串把字母都转为小写(除了I)
  2. 然后进行至多两遍操作
    1. 第一遍把多余空格删除,然后把替换都实现了,因为涉及同时存在you转i,又有i转you,我可以对you can之类转化为I Can,对于 I 转化为You,这样保证修改的是原始串的信息
    2. 第二遍删除了多余空格后,把原本可能隔开很远的you       can之类变成you can,这次目的就是把剩下没有转化的全部转化了。
#include 
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long

bool judnum(char c)//0是字母数字
{
	if ((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9'))return 0;
	else return 1;
}
bool judb(char c)//符号返回1
{
	if (judnum(c)==0||c==' ')return 0;
	else return 1;
}

void mysolve()
{
	int n;
	cin>>n;
	getchar();
	while (n--)
		{
			string s;
			getline(cin,s);
			cout<='A'&&s[i]<='Z'&&s[i]!='I')s[i]=s[i]-'A'+'a';
				}
			string a="";
			bool fl=1;
			while (fl)
				{
					bool flag=1;
					a="";
					fl=0;
					int tk=0;
					int len=(int)s.size();
					for (int i=0; i0)//多个空格
												{
													fl=1;//删除多个空格,需要重来一次
													continue;
												}
											else if (tk==0)
												{
													tk=1;
													a+=' ';
													continue;
												}
										}
									else//不是空格
										{
											tk=0;
											flag=0;
											if (s[i]=='?')
												{
													a+='!';
													continue;
												}
											if (s[i]=='I'&&judnum(s[i-1])&&judnum(s[i+1])&&!(s.substr(i,5)=="I Can"&&judnum(s[i+5]))&&!(s.substr(i,7)=="I Could"&&judnum(s[i+7])))
												{
													a+="You";//大写防止被转化
													continue;
												}
											if (s[i]=='m'&&s[i+1]=='e'&&judnum(s[i-1])&&judnum(s[i+2]))
												{
													i++;
													a+="You";
													continue;
												}
											if (s[i]=='c')
												{
													string tmp=s.substr(i,min((int)s.size()-i+1,7ll));
													if (tmp=="can you"&&judnum(s[i+7])&&(i==0||judnum(s[i-1])))
														{

															a+="I Can";
															i+=6;
															continue;
														}
													tmp=s.substr(i,min((int)s.size()-i+1,9ll));
													if (tmp=="could you"&&judnum(s[i+9])&&(i==0||judnum(s[i-1])))
														{

															a+="I Could";
															i+=8;
															continue;
														}
												}
										}

									a+=s[i];
								}
						}
					while ((int)a.size()&& *a.rbegin()==' ')a.pop_back();//删除后导空格
					s=a;
				}
			for (int i=0; i<(int)a.size(); ++i)
				{
					if (a[i]>='A'&&a[i]<='Z'&&a[i]!='I')a[i]=a[i]-'A'+'a';//因为转化保留一些大写字母,改写回来
				}
			cout<

题目详情 - L2-029 特立独行的幸福 (pintia.cn)

思路:DFS

  1.  数据只有1e4,显然可以暴力出所有幸福数。也可以同时记录每个幸福数有多少个依赖数
  2. 对于区间依附,我们可以判断是否在区间内,从而记录它是否独立
  3. 素数用埃氏筛
#include 
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
const int N = 1e4 + 10;

int vis[N],in[N],book[N];
int a,b;
int getpin(int x)
{
	int ans=0;
	while (x)
		{
			ans+=(x%10)*(x%10);
			x/=10;
		}
	return ans;
}

int dfs(int x)
{
	if (vis[x])return vis[x];//-1表示不是幸福数,1表示是,0表示还未处理
	int v=getpin(x);
	vis[x]=-1;//初始设置为不是,防止循环
	vis[x]=dfs(v);
	if (vis[x]==1)//如果回来检测到他是幸福数,显然v依附x(v由x得到)
		{
			if (x<=b&&x>=a)//如果x在区间内,显然v在区间内有依附,不独立
				book[v]=1;//标记为1就是不独立
			in[x]=in[v]+1;//in表示包括x自己在内的依附与它的数,显然,依附于v的数也依附于x
		}
	return vis[x];
}

bool judsu(int x)//埃氏筛
{
	if (x==1||x==2||x==4)return 0;
	if (x==3||x==5)return 1;
	if (x%6!=1&&x%6!=5)return 0;
	for (int i=5; i*i<=x; i+=6)if (x%i==0||x%(i+2)==0)return 0;
	return 1;
}

void mysolve()
{
	cin>>a>>b;
	vis[1]=in[1]=1;
	for (int i=2; i<=1e4; ++i)
		{
			if (vis[i])continue;
			dfs(i);
		}
	bool flag=0;
	for (int i=a; i<=b; ++i)
		{
			if (vis[i]==1&&!book[i])//是幸福数且独立
				{
					flag=1;
					int ans=in[i]-1;
					if (judsu(i))ans*=2;
					cout<> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

题目详情 - L2-030 冰岛人 (pintia.cn)

思路:

  1. 祖先显然就是一棵(多棵)祖先树。
  2. 我们可以记录每个点的父亲与初代祖先
  3. 之后对初代祖先们dfs建立深度即可
  4. 注意,其他人是不属于祖先树的,所以他们只要性别符合就可以跟冰岛人爱爱 ,不能列入祖先树(会有案例卡)
#include 
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
#define endll            endl< pll;
//---------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------//
const int INF = 0x3f3f3f3f;         //int型的INF
const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF
const int N = 2e5 + 10;

unordered_mapmp;
int cnt;
struct node
{
	int next,to;
} edge[N<<1];
int head[N],num;
void add(int u,int v)
{
	edge[++num].next=head[u];
	edge[num].to=v;
	head[u]=num;
}
bool sex[N];//记录性别,1为男,0为女
int fa[N],in[N],dep[N],pre[N];

void dfs(int u,int fa,int f)//遍历祖先树建立深度
{
	dep[u]=dep[fa]+1;
	pre[u]=f;//标记每个点的初代祖先
	for (int i=head[u]; i; i=edge[i].next)
		{
			int v=edge[i].to;
			dfs(v,u,f);
		}
}

void mysolve()
{
	int n;
	cin>>n;
	string a,b,tmp;
	while (n--)
		{
			cin>>a;
			if (!mp[a])mp[a]=++cnt;
			cin>>b;
			int len=(int)b.size();
			if (b[len-1]=='m')sex[mp[a]]=1;
			else if (b[len-1]=='n')
				{
					sex[mp[a]]=1;
					tmp=b.substr(0,len-4);//是冰岛人就建立关系边
					if (!mp[tmp])mp[tmp]=++cnt;
					fa[mp[a]]=mp[tmp];
					add(mp[tmp],mp[a]);
					in[mp[a]]++;
				}
			else if (b[len-1]=='r')
				{
					tmp=b.substr(0,len-7);
					if (!mp[tmp])mp[tmp]=++cnt;
					fa[mp[a]]=mp[tmp];
					add(mp[tmp],mp[a]);
					in[mp[a]]++;
				}
		}

	for (int i=1; i<=cnt; ++i)if (!in[i])dfs(i,i,i);//对所以初代祖先建立祖先树
	int q;
	cin>>q;
	while (q--)
		{
			cin>>a>>tmp>>b>>tmp;
			int x=mp[a],y=mp[b];
			if (!x||!y)//不存在这个人
				{
					cout<<"NA"<=4)cout<<"Yes"<

题目详情 - L3-022 地铁一日游 (pintia.cn)

思路:它又考floyd了 

  1. 数据1e2求最短路,显然暴力floyd
  2. 对于每个站点,我们可以处理它每个花费可以去的最远的点(当然,如果能到首尾终点站,则无视它是不是最远),最后重新建立点与点之间的单向边构成的有向图。
  3. 因为数据只有1e2,所以每次求一个站点,我们都可以每次来一次dfs求出他能经过的站点
#include 
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
#define endll            endl< pii;
typedef pair pll;
//---------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------//
//double 型memset最大127,最小128
const int INF = 0x3f3f3f3f;         //int型的INF
const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF
const int N = 210;

int dp[N][N],tend[N];
vectoredge[N];
bool vis[N];
void dfs(int u)//dfs求可以经过的点
{
	vis[u]=1;
	for (auto v:edge[u])
		{
			if (!vis[v])dfs(v);
		}
}

void mysolve()
{
	int n,m,k;
	cin>>n>>m>>k;
	memset(dp,0x3f,sizeof(dp));
	int x,w,y;
	while (m--)
		{
			cin>>x;
			tend[x]=1;//tend存储首尾终点站
			while (1)
				{
					cin>>w>>y;
					dp[x][y]=dp[y][x]=min(dp[x][y],w);
					x=y;
					char c=getchar();
					if (c=='\n')break;
				}
			tend[x]=1;
		}
	for (int kk=1; kk<=n; ++kk)for (int i=1; i<=n; ++i)for (int j=1; j<=n; ++j)if (i!=j)dp[i][j]=min(dp[i][j],dp[i][kk]+dp[kk][j]);//floyd
	for (int i=1; i<=n; ++i)
		{
			unordered_mapcost;//cost[p]记录花费p时最远距离
			for (int j=1; j<=n; ++j)
				{
					if (dp[i][j]cost[p])cost[p]=dp[i][j];
						}
				}
			for (int j=1; j<=n; ++j)if (dp[i][j]>q;
	while (q--)
		{
			cin>>x;
			memset(vis,0,sizeof(vis));//询问每次dfs即可,记得初始化
			dfs(x);
			bool flag=1;
			for (int i=1; i<=n; ++i)if (vis[i])
					{
						if (flag)flag=0,cout<> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

题目详情 - L3-023 计算图 (pintia.cn)

思路:还是dfs

  1. 我们只需要从输出点 不断深入模拟,自然就得到函数值,求导也一样,不过不同变量的求导,每个点求导值不一样,所以需要每个变量各自求一遍

#include 
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
#define endll            endl< pii;
typedef pair pll;
//---------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------//
//double 型memset最大127,最小128
const int INF = 0x3f3f3f3f;         //int型的INF
const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF
const int N = 2e5 + 10;
int in[N];
struct node
{
	int x,y,id;//x,y记录运算符的左右值,id表示操作
	double w;//w表示当前函数值
} b[N];
double dm[N];//表示当前节点导数值

double dfs(int u)//求函数
{
	if (b[u].w>n;
	sets;
	int op;
	for (int i=0; i>op;
			b[i].w=INF;
			if (op==0)cin>>b[i].w,s.insert(i);
			else if (op>=1&&op<=3)cin>>b[i].x>>b[i].y,in[b[i].x]++,in[b[i].y]++;
			else cin>>b[i].x,in[b[i].x]++;
			b[i].id=op;
		}
	int fa;
	for (int i=0; i> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

你可能感兴趣的:(acm训练赛补题,c++,算法,图论)