码迷,mamicode.com
首页 > 其他好文 > 详细

NC月赛补题

时间:2020-02-25 09:36:06      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:push   定义   另一个   ret   总结   turn   pat   void   笛卡尔   

NC月赛补题

B-树上子链:

题目描述
给定一棵树 T ,树 T 上每个点都有一个权值。
定义一颗树的子链的大小为:这个子链上所有结点的权值和 。
请在树 T 中找出一条最大的子链并输出。
输入描述:
第一行输入一个 n,1≤n≤10^5。

接下来一行包含n个数,对于每个数ai,-10^5 <= ai <= 10^5,表示 i 结点的权值。
接下来有n-1行,每一行包含两个数u,v( 1 <= u,v <= n,u != v),表示u与v之间有一条边。
输出描述:
仅包含一个数,表示我们所需要的答案。
示例1

输入
5
2 -1 -1 -2 3
1 2
2 3
2 4
2 5

输出
4
说明
样例中最大子链为1 -> 2 -> 5
备注:
一个结点,也可以称作一条链

ps: 巨坑的long long型,不会的图论的我死磕,赶紧学习一波存图再说吧,不过还是感谢某巨佬耐心指导。(以后总结图论)这题和树的直径类似...

AC:


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<stdlib.h>
#include<math.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 7;
const int maxm = 2e5 + 7;
const long long mod = 1e9 + 7;
const long long INF = 0x3f3f3f3f;
LL n,a[maxn],u,v,dp[maxn],ans=-INF;
int vis[maxn];
vector<LL> G[maxn];

void dfs(LL x)
{
    vis[x] = 1; //标记该点已经走过
    LL tmp1 = a[x],tmp2 = a[x]; //tmp1为该节点最长链,tmp2为该节点次长链 
    for(int i = 0; i<G[x].size(); i++)
    {
         if(vis[G[x][i]]) //判断邻接点是否遍历过 
            continue;
         dfs(G[x][i]); //如果未遍历过就先进行遍历
         dp[x] = max(dp[x],dp[G[x][i]] + a[x]); //用dp来存当前该根节点最大权值
         if(dp[G[x][i]] + a[x] > tmp1) //判断是否新的子链大于最长子链 
         {
            tmp2 = tmp1; //将原来的最长子链变成第二长子链
            tmp1 = dp[G[x][i]] + a[x]; 
         } 
         else if(dp[G[x][i]] + a[x] > tmp2) //判断是否新的子链大于次长子链而不是最长子链
            tmp2 = dp[G[x][i]] + a[x]; //更新次长子链 
    } 
    dp[x] = tmp1; //仅有一一个子节点 
    ans = max(ans,tmp1 + tmp2 -a[x]);//最长子链 + 次长子链 - 当前节点权值 
}

int main()
{
    scanf("%lld",&n);
    for(int i = 1; i <= n; i++)
        scanf("%lld",&a[i]);
    for(int i = 1; i < n; i++)
    {
        scanf("%lld%lld",&u,&v);
        G[u].push_back(v); //用邻接表的方式存图 
        G[v].push_back(u);
    }
    memset(vis,0,sizeof(vis));
    dfs(1); //从第一个点开始遍历整个图 
    printf("%lld",ans);
    return 0;
}

D-收集纸片:

题目描述
我们把房间按照笛卡尔坐标系进行建模之后,每个点就有了一个坐标。
假设现在房子里有些纸片需要被收集,收集完纸片你还要回归到原来的位置,你需要制定一个策略来使得自己行走的距离最短。
你只能沿着 x 轴或 y 轴方向移动,从位置 (i,j) 移动到相邻位置 (i+1,j),(i-1,j),(i,j+1) 或 (i,j-1) 距离增加 1。

输入描述:
在第一行中给出一个T, 1≤T≤10, 代表测试数据的组数 。
对于每组输入,在第一行中给出房间大小,第二行给出你的初始位置。
接下来给出一个正整数 n,1≤n≤10 代表纸片的个数。
接下来 n 行,每行一个坐标代表纸片的位置。
保证房间小于 20×20,纸片一定位于房间内。
输出描述:
对于每组输入,在一行中输出答案。
格式参见样例。
示例1
输入

1
10 10
1 1
4
2 3
5 5
9 4
6 5
输出

The shortest path has length 24

AC:


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stdlib.h>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+7;
const int maxm=2e5+7;
const int num=15;
const long long mod=1e9+7;
const long long INF=0x3f3f3f3f;
int minLen=INF;
int a,b,n;
int r,c,t;
int vis[num];
struct node
{
    int x,y;    
}pos[num];


void dfs(int x,int y,int nn,int step)
{
    if(!nn)
    {
        step+=abs(x-r)+abs(y-c);
        minLen=min(minLen,step);
        return;
    }
    for(int k=1;k<=n;k++)
    {
        int xx=pos[k].x;
        int yy=pos[k].y;
        if(!vis[k])
        {
            step+=abs(xx-x)+abs(yy-y);
            vis[k]=1;
            dfs(xx,yy,nn-1,step);
            step-=abs(xx-x)+abs(yy-y);
            vis[k]=0;
        }
    }
}

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d%d",&a,&b,&r,&c,&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&pos[i].x,&pos[i].y);
        memset(vis,0,sizeof(vis));
        dfs(r,c,n,0);
        if(minLen<INF)
            printf("The shortest path has length %d\n",minLen);
        else
            printf("-1\n");
    }
    return 0;
}

E-方块涂色(水题)

题目描述
一块矩形区域被划分为了n行m列的小方格,初始情况下这些方格都是未被上色的。
为了使得矩形看起来不是单一的色彩,现在挑选出r行c列格子并将挑选出的格子上色。
请计算上色完成后,未上色格子的数目。
输入描述:
多组输入
每组输入在一行中给出四个数字 n, m, r, c,含义如题所示。
数据保证有 1<= n, m <= 10^6, 1 <=r <= n, 1 <= c <= m.
输出描述:
每组输入输出一行代表答案。
示例1
输入
5 5 2 3

输出
6

AC:

#include<bits/stdc++.h>
using namespace std;
long long n,m,r,c;
int main()
{
    while(~scanf("%lld%lld%lld%lld",&n,&m,&r,&c))
    {
         printf("%lld\n",n*m-m*r-n*c+r*c);   
    }
    return 0;
}

F-累乘数字(还是水题)

题目描述
我们知道将一个大于1的数乘以另一个大于1的数会使乘积大于任意一个乘数。
现在给出两个数字 n, d,你能否计算将n乘以d次100的结果。
输入描述:
多组输入
每组输入在一行中给出n,d,1≤n,d≤100。
输出描述:
每组输入输出一行代表答案。
示例1
输入
5 1
11 1
85 2

输出
500
1100
850000

AC:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<math.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+7;
const int maxm=2e5+7;
const long long inf=0x3f3f3f3f;
const long long mod=1e9+7;
string n;
char a='0';
int d;
int main()
{
    while(cin>>n>>d)
    {
        for(int i=0;i<d;i++)
        {
            n=n+a;  
            n=n+a;
        }
    cout<<n<<endl;
    }
    return 0;
}


//题解:

#include <bits/stdc++.h>
 
using namespace std;
 
int main(){
    int n, d;
    while (cin >> n >> d){
        cout << n;
        for (int i = 1;i <= d; cout << "00", i++);
        cout << endl;
    }
    return 0;
}

G-仓库选址(暴力枚举)

题目:
牛能在某小城有了固定的需求,为了节省送货的费用,他决定在小城里建一个仓库,但是他不知道选在哪里,可以使得花费最小。
给出一个m×n的矩阵,代表下一年小城里各个位置对货物的需求次数。我们定义花费为货车载货运输的距离,货车只能沿着水平或竖直方向行驶。

输入描述:
首先在一行中输入T , T≤10,代表测试数据的组数。
每组输入在第一行给出两个正整数n, m,1≤n,m≤100,分别代表矩阵的宽和高。
接下来m行,每行n个不超过1000的数字,代表矩阵里的元素。
输出描述:
每组输入在一行中输出答案。
示例1
输入
3
2 2
1 1
1 0
4 4
0 8 2 0
1 4 5 0
0 1 0 1
3 9 2 0
6 7
0 0 0 0 0 0
0 1 0 3 0 1
2 9 1 2 1 2
8 7 1 3 4 3
1 0 2 2 7 7
0 1 0 0 1 0
0 0 0 0 0 0

输出
2
55
162

备注:
送货时只能单次运输,若该位置需要3次,货车必须跑3次。
即使该位置需要被送货,我们仍然可以选择该位置作为仓库。

AC:

//O(n^2 * m^2)也能过...
#include<bits/stdc++.h>
using namespace std;
const int num=105;
int maze[num][num];
int t,n,m,ans;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        ans=0x3f3f3f3f;
        scanf("%d%d",&m,&n);
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
                scanf("%d",&maze[i][j]);
        for(int x = 1;x <= n;x++)
        {
            for(int y = 1;y <= m;y++)
            {
                int sum = 0;
                for(int i = 1;i <= n;i++)
                {
                    for(int j = 1;j <= m;j++)
                    {
                        sum += (abs(x - i) + abs(y - j)) * maze[i][j];
                    }
                }
                ans = min(sum,ans);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

还有剩下的慢慢来吧~~~

NC月赛补题

标签:push   定义   另一个   ret   总结   turn   pat   void   笛卡尔   

原文地址:https://www.cnblogs.com/K2MnO4/p/12359765.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!