题目大意:给定一颗n节点的树,给定几个点,问我们是否能够在树上找到一点到这几个点的距离是一样的
解题思路:我们把这几个点同时放进去并且进行BFS操作,并且我们开一个数组去记录有几个最终结点到这里的最短路径的的条数,因此对于每个经过的结点,我们若有dis[x] == dis[h] + 1,则cnt[x] += cnt[h],如果dis[x] > dis[h] + 1,则cnt[x] = cnt[h]
#include
using namespace std;
const int maxn = 2e5 + 10;
const int inf = 0x3f3f3f3f;
vector G[maxn];
queue q;
int cnt[maxn];
int dis[maxn];
int n,m;
void BFS()
{
while(!q.empty())
{
int x = q.front();
q.pop();
for(int f : G[x])
{
if(dis[f] == dis[x] + 1) cnt[f] += cnt[x];
else if(dis[f] > dis[x] + 1)
{
dis[f] = dis[x] + 1;
cnt[f] = cnt[x];
q.push(f);
}
}
}
}
void solve()
{
scanf("%d %d",&n,&m);
memset(dis,inf,sizeof dis);
for(int i = 1;i <= n - 1;++i)
{
int u,v;
scanf("%d %d",&u,&v);
G[u].emplace_back(v);
G[v].emplace_back(u);
}
int pos;
for(int i = 1;i <= m;++i)
{
scanf("%d",&pos);
dis[pos] = 0;
cnt[pos] = 1;
q.push(pos);
}
//cout << "??"<<"\n";
BFS();
for(int i = 1;i <= n;++i)
{
//cout<
题目大意:给定三维空间中的n个点,找出一个最小四棱锥能够将这些点全部包含在锥体里面,并且输出相应顶点的坐标
题目分析:由于这道题目求的是最小的高度,那么我们可以知道必定会存在一根柱子会与金字塔的面相切,那么对于金子塔上面的任意一个点(非顶点)(xi,yi,zi),和其顶点(x,y,z),对于x来说可以列出这样的式子,那么对于这个绝对值我们也可以进行一个拆分,让式子后面大于等于0,即可获得x的左右边界,同时用这种方法也可以获得y的左右边界,那么最后的点,我们可以知道是(xl + xr >> 1,yl + yr >> 1),对于高度来说,高度是需要取x和y之中长度相对来说比较长的那一根,因此我们也可以输出最后的结果了
#include
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll xr = - inf,xl = inf,yr = - inf,yl = inf;
ll x,y,h;
int n;
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)
{
scanf("%lld %lld %lld",&x,&y,&h);
xr = max(h + x,xr);
xl = min(x - h,xl);
yr = max(h + y,yr);
yl = min(y - h,yl);
}
printf("%lld %lld %lld\n",(xr + xl) >> 1,(yl + yr) >> 1,max((xr - xl + 1),(yr - yl + 1)) >> 1);
return 0;
}
题目大意:找到一个序列满足aj - ai = ak - aj
解题思路:先分析数据范围2000,那么n^2的时间复杂度是肯定可以被接受的,那么我们可以先把前面的 2 aj - ai给算出来,最后再去读入进来ak的时候将答案给计算进去(注意使用unordered_map,还有在使用count的时候时间复杂度会比直接查询要来的小)
#include
using namespace std;
int T,n;
long long ans;
const int maxn = 2e3 + 10;
int a[maxn];
unordered_map mp;
int tmp;
void solve()
{
scanf("%d",&n);
ans = 0;
mp.clear();
for(int i = 1;i <= n;++i)
{
scanf("%d",&a[i]);
if(mp.count(a[i]) != 0) ans += mp[a[i]];
for(int j = 1;j < i;++j)
{
mp[2 * a[i] - a[j]]++;
}
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
题目大意:给定一张图,aij代表从i到j的路有aij % 10条
解题思路:分析数据范围,数据范围比较小,那么我们可以直接通过枚举中间那个来判断相对应的路是否符合我们的要求
#include
using namespace std;
const int maxn = 5e2 + 10;
int mp[maxn][maxn];
char str[maxn][maxn];
int ans[maxn][maxn];
int n;
void solve()
{
scanf("%d",&n);
//getchar();
for(int i = 1;i <= n;++i)
{
scanf("%s",str[i] + 1);
// printf("%s\n",str[i] + 1);
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
//printf("str: %s",str[i]);
mp[i][j] = str[i][j] - '0';
}
}
// for(int i = 1;i <= n;++i)
// {
// for(int j = 1;j <= n;++j)
// {
// printf("%d ",mp[i][j]);
// }
// printf("\n");
// }
for(int k = 1;k <= n;++k)
{
for(int i = 1;i <= n - k;i++)
{
int f = i + k,cnt = 0;
for(int j = i + 1;j < f;++j)
{
cnt = (cnt + ans[i][j] * mp[j][f]) % 10;
}
if(cnt != mp[i][f]) ans[i][f] = 1;
}
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
printf("%d",ans[i][j]);
}
printf("\n");
}
}
int main()
{
solve();
return 0;
}