牛客网国庆集训派对Day6 题目 2018年

链接:https://www.nowcoder.com/acm/contest/206/A
来源:牛客网

Birthday

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld

题目描述

恬恬的生日临近了。宇扬给她准备了一个蛋糕。
正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为m个区域。因为某种原因,他必须把第i根蜡烛插在第a i个区域或第b i个区域。区域之间是不相交的。宇扬在一个区域内同时摆放x支蜡烛就要花费x 2的时间。宇扬布置蛋糕所用的总时间是他在每个区域花的时间的和。
宇扬想快些见到恬恬,你能告诉他布置蛋糕最少需要多少时间吗?

输入描述:

第一行包含两个整数n,m(1 ≤ n ≤ 50, 2≤ m≤ 50)。
接下来n行,每行两个整数a
i
,b
i
(1 ≤ a
i
, b
i
 ≤ m)。

输出描述:

一个整数表示答案。
示例1

输入

复制
3 3
1 2
1 2
1 2

输出

复制
5
示例2

输入

复制
3 3
1 2
2 3
1 3

输出

复制
3
思路:最小费用最大流。
代码:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <queue>
 5   
 6 using namespace std;
 7   
 8 const int INF = 0x3f3f3f3f;
 9 const int MAXN = 5005;
10   
11 struct Edge{
12     int value,flow,to,rev;
13     Edge(){}
14     Edge(int a,int b,int c,int d):to(a),value(b),flow(c),rev(d){}
15 };
16   
17 vector<Edge> E[MAXN];
18   
19 inline void Add(int from,int to,int flow,int value){
20     E[from].push_back(Edge(to,value,flow,E[to].size()));
21     E[to].push_back(Edge(from,-value,0,E[from].size()-1));
22 }
23   
24 bool book[MAXN];//用于SPFA中标记是否在queue中
25 int cost[MAXN];//存费用的最短路径
26 int pre[MAXN];//存前节点
27 int pree[MAXN];//存在前节点的vector中的下标
28   
29 bool Spfa(int from,int to){
30     memset(book,false,sizeof book);
31     memset(cost,INF,sizeof cost);
32     book[from] = true;
33     cost[from] = 0;
34     queue<int> Q;
35     Q.push(from);
36     while(!Q.empty()){
37         int t = Q.front();
38         book[t] = false;
39         Q.pop();
40         for(int i=0 ; i<E[t].size() ; ++i){
41             Edge& e = E[t][i];
42             if(e.flow > 0 && cost[e.to] > cost[t] + e.value){
43                 cost[e.to] = cost[t] + e.value;
44                 pre[e.to] = t;
45                 pree[e.to] = i;
46                 if(book[e.to] == false){
47                     Q.push(e.to);
48                     book[e.to] = true;
49                 }
50             }
51         }
52     }
53     return cost[to] != INF;
54 }
55   
56 int Work(int from,int to){
57     int sum = 0;
58     while(Spfa(from,to)){
59         int mflow = INF;//SPFA找到的最短路径的最小容量
60         int flag = to;
61         while(flag != from){
62             mflow = min(mflow,E[pre[flag]][pree[flag]].flow);
63             flag = pre[flag];
64         }
65         flag = to;
66         while(flag != from){
67             sum += E[pre[flag]][pree[flag]].value * mflow;
68             E[pre[flag]][pree[flag]].flow -= mflow;
69             E[flag][E[pre[flag]][pree[flag]].rev].flow += mflow;
70             flag = pre[flag];
71         }
72     }
73     return sum;
74 }
75   
76 int main(){
77      
78     int N,M;
79     while(scanf("%d %d",&N,&M) == 2){
80         int a,b;
81         for(int i=1 ; i<=N ; ++i){
82             scanf("%d %d",&a,&b);
83             Add(i,a+N,1,0);
84             Add(i,b+N,1,0);
85             Add(0,i,1,0);
86         }
87         for(int i=1 ; i<=M ; ++i){
88             for(int j=1 ; j<=99 ; j+=2){//99 = 2*50-1;
89                 Add(i+N,M+N+1,1,j);
90             }
91         }
92         printf("%d\n",Work(0,M+N+1));
93         for(int i=0 ; i<=M+N+1 ; ++i)E[i].clear();
94     }
95      
96     return 0;
97 }

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

Board

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld

题目描述

恬恬有一个nx n的数组。她在用这个数组玩游戏:
开始时,数组中每一个元素都是0。
恬恬会做某些操作。在一次操作中,她可以将某一行的所有元素同时加上一个值,也可以将某一列的所有元素同时加上一个值。
在几次操作后,一个元素被隐藏了。你能帮助她回忆隐藏的数是几吗?

输入描述:

第一行一个整数n(1≤ n≤ 1000)。
接下来n行每行n个整数表示数组a。
第(i+1)行的第j个元素表示a
ij
(a
ij
=-1或0≤ a
ij
 ≤ 10000)。-1表示隐藏的元素。

输出

仅一个整数表示答案。
示例1

输入

复制
3
1 2 1
0 -1 0
0 1 0

输出

复制
1

思路:先把每一行先减去每一行的最小值,然后找到“-1”所在的行和列(行和列的各自的最小值的和即为所求)
代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=1e9+5;
 4 int a[1010][1010];
 5 int main()
 6 {
 7     int n;
 8     int x,y;
 9     scanf("%d",&n);
10     for(int i=1; i<=n; i++)
11     {
12         for(int j=1; j<=n; j++)
13         {
14             scanf("%d",&a[i][j]);
15             if(a[i][j]==-1)
16             {
17                 x=i,y=j;
18             }
19  
20         }
21     }
22     int sum;
23     for(int i=1; i<=n; i++)
24         {
25             sum==inf;
26             if(i==x)
27                 continue;
28             for(int j=1;j<=n;j++)
29             {
30                 sum=min(sum,a[i][j]);
31             }
32             for(int j=1;j<=n;j++)
33             {
34                 a[i][j]-=sum;
35             }
36         }
37     for(int i=1; i<=n; i++)
38         {
39             sum==inf;
40             if(i==y)
41                 continue;
42             for(int j=1;j<=n;j++)
43             {
44                 sum=min(sum,a[j][i]);
45             }
46             for(int j=1;j<=n;j++)
47             {
48                 a[j][i]-=sum;
49             }
50         }
51         int tmp1=inf,tmp2=inf;
52         for(int i=1;i<=n;i++)
53         {
54             if(i==x)
55             {
56                 continue;
57             }
58             tmp1=min(tmp1,a[i][y]);
59         }
60         for(int i=1;i<=n;i++)
61         {
62             if(i==y)
63             {
64                 continue;
65             }
66             tmp2=min(tmp2,a[x][i]);
67         }
68         printf("%d\n",tmp1+tmp2);
69     return 0;
70 }
链接: https://www.nowcoder.com/acm/contest/206/C
来源:牛客网

Circle

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld

题目描述

现在我们要把 这n个数字首尾连接组成一个环,使得相邻元素互质的对数尽可能多。请输出最大对数。

输入描述:

一行一个整数n(1≤ n≤ 1000)。

输出描述:

一行一个整数表示答案。
示例1

输入

复制
4

输出

复制
4

说明

样例的一种构造方法为1 4 3 2。
思路:输入n,输出n,此时的排序方式为1,n,n-1,n-2,n-3,,,,,5,4,3,2
代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 int main()
 5 {
 6     int n;
 7     scanf("%d",&n);
 8     printf("%d\n",n);
 9     return 0;
10 }
链接:https://www.nowcoder.com/acm/contest/206/H
来源:牛客网

Mountain

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld

题目描述

平面上有n座山,每座山都有左右两面,第i座山的高度为a i,现在弱弱在第一座山的左边山脚下(高度为0),他想要依此爬过这些山,到达第n座山的右边山脚下。
除了简单的爬上爬下,还有一种特殊操作。
如果弱弱目前在第i座山右面的海拔x的位置,且第j ( i < j )座山的海拔大于等于x,且第 座山中没有一座山的海拔高于x,那么他可以使用绳索滑到第j座山左面海拔x的位置。
弱弱想找到一种方式,使得他在行程中海拔变化的幅度最小。请输出最小幅度。

输入描述:

第一行一个整数n(1≤ n≤ 1000)。
接下来一行n个整数a
i
(1≤ a
i
≤ 1000)表示每座山的高度。

输出描述:

一行一个整数表示答案。
示例1

输入

复制
5
1 3 5 4 2

输出

复制
10
思路:最高点的两倍。
代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[1010];
 4 int main()
 5 {
 6     int n;
 7     scanf("%d",&n);
 8     for(int i=0;i<n;i++)
 9     {
10         scanf("%d",&a[i]);
11     }
12     sort(a,a+n);
13     printf("%d\n",2*a[n-1]);
14     return 0;
15 }
链接:https://www.nowcoder.com/acm/contest/206/E
来源:牛客网

Growth

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld

题目描述

弱弱有两个属性a和b,这两个属性初始的时候均为0,每一天他可以通过努力,让a涨1点或b涨1点。
为了激励弱弱努力学习,我们共有n种奖励,第i种奖励有x i,y i,z i三种属性,若a≥ x i且b≥ y i,则弱弱在接下来的每一天都可以得到z i的分数。
问m天以后弱弱最多能得到多少分数。

输入描述:

第一行一个两个整数n和m(1≤ n≤ 1000,1≤ m≤ 2000000000)。
接下来n行,每行三个整数x
i
,y
i
,z
i
(1≤ x
i
,y
i
≤ 1000000000,1≤ z
i
 ≤ 1000000)。

输出描述:

一行一个整数表示答案。
示例1

输入

复制
2 4
2 1 10
1 2 20

输出

复制
50

备注:

在样例中,弱弱可以这样规划:第一天a涨1,第二天b涨1,第三天b涨1,第四天a涨1。
共获得0+0+20+30=50分。

思路:离散+DP
代码:
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 const int maxn = 1e3 + 100;
 6 
 7 map<pair<int, int>, int> p;
 8 set<int> sx, sy;
 9 int x[maxn], y[maxn];
10 ll dp[maxn][maxn], v[maxn][maxn];
11 
12 int main()
13 {
14    int n, m;
15    int cnt1 = 1, cnt2 = 1;
16    scanf("%d %d", &n, &m);
17    for(int i = 0; i < n; i++) {
18        int tx, ty, tz;
19        scanf("%d %d %d", &tx, &ty, &tz);
20        p[pair<int, int>(tx, ty)] += tz;
21        if(!sx.count(tx)) sx.insert(tx), x[cnt1++] = tx;
22        if(!sy.count(ty)) sy.insert(ty), y[cnt2++] = ty;
23    }
24 
25    sort(x + 1, x + cnt1);
26    sort(y + 1, y + cnt2);
27 
28    for(int i = 1; i < cnt1; i++) {
29      for(int j = 1; j < cnt2; j++) {
30         if(!p[pair<int, int>(x[i], y[j])]) v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1];
31         else v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + p[pair<int, int>(x[i], y[j])];
32      }
33    }
34 
35    for(int i = 0; i < cnt1; i++) {
36       for(int j = 0; j < cnt2; j++) {
37         dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] + (x[i + 1] - x[i] - 1) * v[i][j] + v[i + 1][j]);
38         dp[i][j + 1] = max(dp[i][j + 1], dp[i][j] + (y[j + 1] - y[j] - 1) * v[i][j] + v[i][j + 1]);
39       }
40    }
41 
42    ll ans = 0;
43    for(int i = 1; i < cnt1; i++) {
44     for(int j = 1; j < cnt2; j++) {
45         ll t = dp[i][j] + (m - x[i] - y[j]) * v[i][j];
46         ans = max(ans, t);
47     }
48    }
49    printf("%lld\n", ans);
50 }

参考博客:https://blog.csdn.net/deerly_/article/details/81584521



 
 

猜你喜欢

转载自www.cnblogs.com/weixq351/p/9749026.html