牛客网国庆集训派对Day6 题目 2018年
链接:https://www.nowcoder.com/acm/contest/206/A
来源:牛客网
Birthday
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld
题目描述
恬恬的生日临近了。宇扬给她准备了一个蛋糕。
正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为m个区域。因为某种原因,他必须把第i根蜡烛插在第ai个区域或第bi个区域。区域之间是不相交的。宇扬在一个区域内同时摆放x支蜡烛就要花费x2的时间。宇扬布置蛋糕所用的总时间是他在每个区域花的时间的和。
宇扬想快些见到恬恬,你能告诉他布置蛋糕最少需要多少时间吗?
正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为m个区域。因为某种原因,他必须把第i根蜡烛插在第ai个区域或第bi个区域。区域之间是不相交的。宇扬在一个区域内同时摆放x支蜡烛就要花费x2的时间。宇扬布置蛋糕所用的总时间是他在每个区域花的时间的和。
宇扬想快些见到恬恬,你能告诉他布置蛋糕最少需要多少时间吗?
输入描述:
第一行包含两个整数n,m(1 ≤ n ≤ 50, 2≤ m≤ 50)。i
接下来n行,每行两个整数a
,bi
(1 ≤ ai
, bi
≤ m)。
输出描述:
一个整数表示答案。
示例2
输出
复制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
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld
题目描述
恬恬有一个nx n的数组。她在用这个数组玩游戏:
开始时,数组中每一个元素都是0。
恬恬会做某些操作。在一次操作中,她可以将某一行的所有元素同时加上一个值,也可以将某一列的所有元素同时加上一个值。
在几次操作后,一个元素被隐藏了。你能帮助她回忆隐藏的数是几吗?
开始时,数组中每一个元素都是0。
恬恬会做某些操作。在一次操作中,她可以将某一行的所有元素同时加上一个值,也可以将某一列的所有元素同时加上一个值。
在几次操作后,一个元素被隐藏了。你能帮助她回忆隐藏的数是几吗?
输入描述:
第一行一个整数n(1≤ n≤ 1000)。ij
接下来n行每行n个整数表示数组a。
第(i+1)行的第j个元素表示a
(aij
=-1或0≤ aij
≤ 10000)。-1表示隐藏的元素。
输出
仅一个整数表示答案。
示例1
输出
复制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
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld
题目描述
代码:
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
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld
题目描述
平面上有n座山,每座山都有左右两面,第i座山的高度为ai,现在弱弱在第一座山的左边山脚下(高度为0),他想要依此爬过这些山,到达第n座山的右边山脚下。
除了简单的爬上爬下,还有一种特殊操作。
如果弱弱目前在第i座山右面的海拔x的位置,且第j ( i < j )座山的海拔大于等于x,且第座山中没有一座山的海拔高于x,那么他可以使用绳索滑到第j座山左面海拔x的位置。
弱弱想找到一种方式,使得他在行程中海拔变化的幅度最小。请输出最小幅度。
除了简单的爬上爬下,还有一种特殊操作。
如果弱弱目前在第i座山右面的海拔x的位置,且第j ( i < j )座山的海拔大于等于x,且第座山中没有一座山的海拔高于x,那么他可以使用绳索滑到第j座山左面海拔x的位置。
弱弱想找到一种方式,使得他在行程中海拔变化的幅度最小。请输出最小幅度。
输入描述:
第一行一个整数n(1≤ n≤ 1000)。i
接下来一行n个整数a
(1≤ ai
≤ 1000)表示每座山的高度。
输出描述:
一行一个整数表示答案。
思路:最高点的两倍。
代码:
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
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld
题目描述
弱弱有两个属性a和b,这两个属性初始的时候均为0,每一天他可以通过努力,让a涨1点或b涨1点。
为了激励弱弱努力学习,我们共有n种奖励,第i种奖励有xi,yi,zi三种属性,若a≥ xi且b≥ yi,则弱弱在接下来的每一天都可以得到zi的分数。
问m天以后弱弱最多能得到多少分数。
为了激励弱弱努力学习,我们共有n种奖励,第i种奖励有xi,yi,zi三种属性,若a≥ xi且b≥ yi,则弱弱在接下来的每一天都可以得到zi的分数。
问m天以后弱弱最多能得到多少分数。
输入描述:
第一行一个两个整数n和m(1≤ n≤ 1000,1≤ m≤ 2000000000)。i
接下来n行,每行三个整数x
,yi
,zi
(1≤ xi
,yi
≤ 1000000000,1≤ zi
≤ 1000000)。
输出描述:
一行一个整数表示答案。
备注:
在样例中,弱弱可以这样规划:第一天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 }
雪儿言