牛客算法周周练13 A.stl B.dfs(树的重心) C.贪心 D.模拟 E.DP

链接:https://ac.nowcoder.com/acm/contest/6173/A
来源:牛客网
A
题目描述
小 A 有一张 n 个点的带权无向图,这张无向图非常特别,首先第 i 个点有一个点权 ai,之后这张无向图是一张完全图,且边 (u,v) 的权值为 au+av
现在小 A 想找一个这张图的边权之和最小的生成树,需要你来帮帮他
输入描述:
第一行一个正整数 n
第二行 n 个整数 a1,a2…an
输出描述:
输出边权和最小的生成树的边权之和
示例1
1
输入
复制
3
1 2 3
输出
复制
7
备注:
1≤ n≤ 1e5
0≤ ai≤ 1e9

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
ll n,ans;
ll a[110005];
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
     cin>>a[i];
  }
  sort(a,a+n);
  for(int i=1;i<n;i++){
     ans+=a[i]+a[0];
  }
  cout<<ans<<endl;
  return 0;

}

B
链接:https://ac.nowcoder.com/acm/contest/6173/B
来源:牛客网

题目描述
有一天clccle和rqy走在某个国家的街头上,机智的rqy却发现周围的行人不太对劲,他们嘴里念念有词,说着"sqn tql!",一边漫无目的的行走,clccle也发现了这一点,却惊讶的发觉这种奇怪的病毒会向周围的城市,最终会感染整个国家,因为网络已经崩溃,所以她们忘记了自己所在的城市,她们唯一知道的是这种病毒是从当前她们所在的城市开始传播的,并且这个国家的所有城市到这个城市的距离和最小(所有道路的距离都为1),现在给定聪明的你一张整个国家的地图,请你帮rqy和clccle找到她们现在可能在这个国家的哪一个城市.
输入描述:
两个整数n,m,代表这个国家一共有n个城市,城市之间只有m条道路

接下来m行,每行两个整数a,b代表城市a,b之间有一条联通的道路
输出描述:
多个整数,输出当前clccle和rqy可能所在的点
示例1
输入
复制
2 1
1 2
输出
复制
1 2
备注:
对于所有的数据,1<=m<=n<=50000

(图的类型保证没有大小大于等于3的环)

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <climits>
#include <map>
#include <cmath>
#include <set>
using namespace std;
typedef long long ll;
const int maxn=5e4+5;
vector<int>adj[maxn];
int minn[maxn],a[maxn];
int m,n;
void dfs(int u,int fa){
    a[u]=1;
    for(int i=0;i<adj[u].size();i++){
        int v=adj[u][i];
        if(fa==v)continue;
        dfs(v,u);
        a[u]+=a[v];
        minn[u]=max(a[v],minn[u]);
    }
    minn[u]=max(minn[u],n-a[u]);
    return ;
}
int main()
{   ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
   int a,b;
   cin>>n>>m;
   while(m--){
       cin>>a>>b;
       adj[a].push_back(b);
       adj[b].push_back(a);
        
   }
  dfs(1,0);
  int t=0x3f3f3f3f;
  for(int i=1;i<=n;i++){
      t=min(t,minn[i]);
  }
  for(int i=1;i<=n;i++){
      if(minn[i]==t){
         cout<<i<<" ";
      }
  }
  return 0;
}

C
链接:https://ac.nowcoder.com/acm/contest/6173/C
来源:牛客网

题目描述
你要买n件物品,其中有一些是凳子。
商场正在举行促销活动,如果购物车中有至少一个凳子,那么你可以半价购买这个购物车中最贵的一个物品。
你有m辆购物车,请最小化你的花费。
输入描述:
第一行一个整数t表示数据组数 (1 ≤ t ≤ 100)。
每组数据第一行两个整数n,m (1 ≤ n,m ≤ 1000),接下来n行每行两个整数ai,bi,分别表示第i件物品的价格以及它是否是凳子 (1 ≤ ai ≤ 105, 0 ≤ bi ≤ 1)。
输出描述:
每组数据输出一行一个实数表示最小花费,保留一位小数。
示例1
输入
复制
2
5 1
1 0
2 1
3 1
4 0
5 0
5 10
1 0
2 1
3 1
4 0
5 0
输出
复制
12.5
10.5

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <climits>
#include <map>
#include <cmath>
#include <set>
using namespace std;
typedef long long ll;
const int maxn=10005;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int a[maxn];
int main()
{   
   int t,n,m,b,deng;
   double ans=0;
   scanf("%d",&t);
   while(t--){
       deng=0;
       ans=0;
     scanf("%d%d",&n,&m);
     for(int i=0;i<n;i++){
         scanf("%d%d",&a[i],&b);
         if(b==1)deng++;
     }
     sort(a,a+n);
    int t=min(m,deng);
    for(int i=0;i<n-t;i++){
        ans+=a[i];
    }
    for(int i=n-t;i<n;i++){
        ans+=a[i]/2.0;
    }
    printf("%.1f\n",ans);
   }
   
   return 0;
}

D

链接:https://ac.nowcoder.com/acm/contest/6173/D
来源:牛客网

题目描述
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有n张地毯,编号从1到n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
输入描述:
第一行,一个整数n,表示总共有n张地毯。
接下来的n行中,第i+1行表示编号i的地毯的信息,包含四个正整数a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a,b)以及地毯在x轴和y轴方向的长度。
第n+2行包含两个正整数x和y,表示所求的地面的点的坐标(x,y)。
输出描述:
输出共1行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1。
示例1
输入
复制
3
1 0 2 3
0 2 3 3
2 1 3 3
2 2
输出
复制
3
说明
如下图,1号地毯用实线表示,2号地毯用虚线表示,3号用双实线表示,覆盖点(2,2)的最上面一张地毯是3号地毯。

备注:
对于30%的数据,有n≤2;
对于50%的数据,有0≤a,b,g,k≤100;
对于100%的数据,有0≤n≤10,000,0≤a,b,g,k≤100,000。

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=10005;
struct node{
	int a,b;
	int x,y;
}a[maxn];
int main(){
  int n;
  cin>>n;
  int x,y;
  int ans=-1;
  for(int i=1;i<=n;i++){
  	cin>>a[i].a>>a[i].b>>a[i].x>>a[i].y;
  }
  cin>>x>>y;
  for(int i=n;i;i--){
  	if((a[i].a<=x&&a[i].b<=y)&&(a[i].a+a[i].x>=x&&a[i].b+a[i].y>=y)){
  		ans=i;
  		break;
	  }
  }
  cout<<ans<<endl;
  return 0;
} 

E

链接:https://ac.nowcoder.com/acm/contest/6173/E
来源:牛客网

题目描述
最近,奶牛们热衷于把金币包在面粉里,然后把它们烤成馅饼。第i块馅饼中含有Ni(1<=Ni<=25)块金币,并且,这个数字被醒目地标记在馅饼表面。
奶牛们把所有烤好的馅饼在草地上排成了一个R行(1<=R<=100)C列(1<=C<=100)的矩阵。你现在站在坐标为(1,1)的馅饼边上,当然,你可以拿到那块馅饼里的所有金币。你必须从现在的位置,走到草地的另一边,在坐标为(R,C)的馅饼旁边停止走动。每做一次移动,你必须走到下一列的某块馅饼旁边,并且,行数的变动不能超过1(也就是说,如果现在你站在坐标为(r,c)的馅饼边上,下一步你可以走到坐标为(r-1,c+1),(r,c+1),或者(r+1,c+1)的馅饼旁边)。当你从一块馅饼边经过,你就可以拿走馅饼里所有的金币。当然啦,你一定不会愿意因半路离开草地而失去唾手可得的金币,但,最终你一定得停在坐标为(R,C)的馅饼旁边。
现在,你拿到了一张标记着馅饼矩阵中,每一块馅饼含金币数量的表格。那么,按照规则,你最多可以拿到多少金币呢?
比方说,奶牛们把馅饼排成如下的矩阵,矩阵中的数字表示该位置的馅饼中含金币的数量:

起点-> 6 5 3 7 9 2 7
2 4 3 5 6 8 6
4 9 9 9 1 5 8 <-终点
以下是一条合法的路线:

起点-> 6 5 3 7 9 2 7

2 4 3 5 6 8 6
\ /
4 9 9-9 1 5-8 <-终点
按上述的路线进行走动,一共可以获得6+4+9+9+6+5+8=47个金币。按照规则,在这个矩阵中最多可以得到50个金币,路线如下图所示:

起点-> 6 5 3 7 9 2 7

2 4 3 5 6-8 6
\ /
4 9 9-9 1 5 8 <-终点
(请复制到记事本中用等宽字体查看)

输入描述:
第1行: 两个用空格隔开的整数,R和C
第2…R+1行: 每行包含C个用空格隔开的正整数,依次表示一行中从左往右各个馅饼里金币的数量
输出描述:
第1行: 输出一个正整数,表示你所能收集到的最大金币数目
示例1
输入
复制
3 7
6 5 3 7 9 2 7
2 4 3 5 6 8 6
4 9 9 9 1 5 8
输出
复制
50

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <climits>
#include <map>
#include <cmath>
#include <set>
using namespace std;
typedef long long ll;
vector<int>adj[5005];
const int maxn=110;
typedef pair<int,int>p;
int dp[maxn][maxn],a[maxn][maxn];
int main()
{   ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
   int n,m;
   cin>>n>>m;
   for(int i=1;i<=n;i++){
       for(int j=1;j<=m;j++){
           cin>>a[i][j];
       }
   }
   dp[1][1]=a[1][1];
   for(int j=1;j<=m;j++){
       for(int i=1;i<=n;i++){
           if(i>j)break;
           if(i==j)dp[i][j]=dp[i-1][j-1]+a[i][j];
           else dp[i][j]=a[i][j]+max(dp[i-1][j-1],max(dp[i][j-1],dp[i+1][j-1]));
       }
   }
   cout<<dp[n][m];
   return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值