A:
题意:给你n个数,让你找到一个数d使得这n个数除2得到的正整数大于等于n/2向下取整,让你输出这个d。
思路:看有几个正数几个负数,如果整数大于n/2 就输出1,反正输出-1,如果不够输出0
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4+10;
int a[maxn];
int main()
{
int n;
scanf("%d",&n);
int sum1 = 0 , sum2 = 0;
for(int i = 0 ; i < n ; i++)
{
scanf("%d",&a[i]);
if(a[i] > 0) sum1++;
else if(a[i] < 0) sum2++;
}
if(n&1) n++;
if(sum1 >= n/2) puts("1");
else if(sum2 >= n/2) puts("-1");
else puts("0");
}
B:
题意:给你一组数,从1~n每个数都有两个,然后你要从1走到n,之后在从1走到n,第一次和第二次走的点不能重复,问你最短距离是多少
思路:假设1的点为a,b ,2的点为c,d 那么每次走的选择就两种 dis(a,c)+dis(b,d) 或者 dis(a,d) + dis(b,c) 取一个min就好
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
struct node
{
int val , pos;
}edg[maxn];
int dis(int x,int y)
{
return abs(edg[x].pos - edg[y].pos);
}
int main()
{
int n;
scanf("%d",&n);
for(int i = 0 ; i < 2*n ; i++)
{
scanf("%d",&edg[i].val);
edg[i].pos = i;
}
edg[2*n].val = 0;
edg[2*n].pos = 0;
edg[2*n+1].val = 0;
edg[2*n+1].pos = 0;
n++;
sort(edg,edg+2*n,[](node a,node b){return a.val < b.val;});
long long ans = 0;
for(int i = 0 ; i < 2*(n-1); i = i + 2)
{
ans = ans + min(dis(i,i+2)+dis(i+1,i+3) , dis(i+1,i+2) + dis(i,i+3));
}
cout<<ans<<endl;
}
C:
题意: 给你一个图,其中1代表的是海洋,0代表的是陆地,之后给你一个起点和终点,你在陆地上可以走4个方向,且花费为0,你不能在海洋里走,但可以架一座桥,架一座桥的花费是(x1-x2) * (x1-x2) + (y1-y2) *(y1-y2),且这个地图只能架一座桥现在问你从起点走到终点的最小价值是多少:
思路:由题意可以,我们分别从起点和终点开始染色,染完之后,假如起点和终点染的是同一种颜色那么表示可以从起点走到终点,输出0,倘如不一样,那么就说明他们不能走到,由于n只有50所以我们可以暴力取枚举起点和终点染上不同的点(也就是分隔两地的情况) 之后维护一个最小值就好了
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50;
char ch[maxn][maxn];
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
int vis[maxn][maxn];
int sx,ex,sy,ey,n;
void dfs(int x,int y,int p)
{
if(p == 1 && x == ex && y == ey)
{
puts("0");
exit(0);
}
vis[x][y] = p;
for(int i = 0 ; i < 4 ; i++)
{
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if(dx < n && dx >= 0 && dy < n && dy >= 0 && ch[dx][dy] != '1' && vis[dx][dy] == 0)
{
dfs(dx,dy,p);
}
}
}
int main()
{
scanf("%d",&n);
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
sx--,sy--,ex--,ey--;
for(int i = 0 ; i < n ; i++) scanf("%s",ch[i]);
dfs(sx,sy,1);
dfs(ex,ey,-1);
int ans = 0x3f3f3f3f;
for(int i = 0 ; i < n ; i++)
{
for(int j = 0 ; j < n ; j++)
{
for(int k = 0 ; k < n ; k++)
{
for(int l = 0 ; l < n ; l ++)
{
if(vis[i][j] == 1 && vis[k][l] == -1)
{
ans = min(ans,(i-k) * (i-k) + (j - l) * (j-l));
}
}
}
}
}
cout<<ans<<endl;
}
D:
题意:给你n个站点,每个站点有一些糖果,糖果上的编号表示的是你要将这些糖果运输到对应的站点,每次火车到达一个站点,只能选择一个糖果放到火车上,火车的容量无限, 问你每次以i为起点把所有糖果都送到相对应的位置的最小值是多少。
思路:假设我们以i点为起点,那么我们把每个站点的糖果都送完的值是可以算出来的,假设我们现在在j站点,那么我们无论如何都要走 :j 站点的糖果数-1圈 + 从j站点到在j站点的最后一个糖果要去的地方,如何判断找到最后一个点? 我们可以暴力枚举j站点的所有糖果
然后取一个最小值,就是运输完j站点的所有糖果的最小值,之后我们枚举每一个点,在这儿维护一个最大值,为什么要维护最大值? 因为假设我们送完第j个站点所用的时间是t1,送完第k个站点所用的时间是t2,然后t1>t2,那么我们送完这两个站点的最小时间应该是多少?显然是t1,因为t2时间呢j站点的糖果还没有送完
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5000 + 100;
vector<int>G[maxn];
int cur[maxn];
const int INF = 0x3f3f3f3f;
int main()
{
int n , m , maxn = 0 , a,b;
scanf("%d%d",&n,&m);
for(int i = 0 ; i < m ; i++)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
}
for(int i = 1 ; i <= n ; i++) // 枚举起点
{
int ans = 0 ;
for(int j = 1 ; j <= n ; j++) // 枚举以i为起点的所有站点
{
int num = G[j].size() , te = INF;
if(num == 0) continue;
for(auto v : G[j])
{
te = min(te , (num-1) * n + (j-i+n)%n + (v-j+n)%n); // 送完j站点的时间为 dis(i,j) + dis(j,v)意思是 起点i到j站点的距离,加上j站点到最后一个站点的距离
}
ans = max(ans,te);
}
cout<<ans<<" ";
}
}