A:Birthday

时间限制: 1 Sec  内存限制: 256 MB

题目描述

恬恬的生日临近了。宇扬给她准备了一个大蛋糕。

正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为m个区域。因为某种原因,他必须把第i根蜡烛插在第ai个区域或第bi个区域。区域之间是不相交的。宇扬在一个区域内同时摆放x支蜡烛就要花费x2的时间。宇扬布置蛋糕所用的总时间是他在每个区域花的时间的和。

宇扬想快些见到恬恬,你能告诉他布置蛋糕最少需要多少时间吗?

输入

第一行包含两个整数nm(1 ≤ n ≤ 50, 2 ≤ m ≤ 50)。

接下来n行,每行两个整数ai, bi(1 ≤ ai, bim)。

输出

一个整数表示答案.

样例输入

3 3
1 2
1 2
1 2

样例输出

5

唉,还是大佬的题解写的好,所以感谢wls大佬分享思路  Orz。。。

思路:考虑费用流时把每个part拆成n个点,选择第i个点的代表为放置i块蛋糕和(i - 1)块蛋糕的时间差,

这个时间差是递增的,因此在费用流的过程中必定会从小到大选择

具体建图:

左边n个点代表n个蛋糕,右边m * n个点代表m个part,每个part拆成n个点。源点向每个左边的点连一条流量1费用0的边,每个右边的点向汇点连一条流量1费用0的编。

每个蛋糕向可以放的两个part的所有点连边,连向第i个点的费用为i^2 - (i - 1)^2,流量为1。这样求最小费用流既为答案。

#include"bits/stdc++.h"
using namespace std;
#define M 1100
const int inf=0x7fffffff;
struct node{
int u,v,c,f,next; //C为花费,F为flow流量
}e[M*40];
int pre[M],dis[M],head[M],t;
int vis[M]; void add1(int u,int v,int c,int f){
e[t].u=u;
e[t].v=v;
e[t].c=c;
e[t].f=f;
e[t].next=head[u];
head[u]=t++;
} void add(int u,int v,int c,int f){
add1(u,v,c,f);
add1(v,u,-c,0); //反向边流量初始为零,如果走反向边费用正好和原边抵消
} int spfa(int s,int t){
int i,u,v;
queue<int>q;
q.push(s);
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(i=s;i<=t;i++)
dis[i]=inf;
dis[s]=0;
while(!q.empty()){
u=q.front();
q.pop();
for(i=head[u];i!=-1;i=e[i].next)
{
v=e[i].v;
if(e[i].f&&dis[v]>dis[u]+e[i].c) //找到一条最小费用流
{
dis[v]=dis[u]+e[i].c;
pre[v]=i; //记录路径
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
vis[u]=0;
}
if(dis[t]!=inf)
return 1;
return 0;
} void solve(int s,int t){
int ans=0,i,j;
int flow=0,cost=0; //总流量、总费用
while(spfa(s,t)){
int minf=inf;
for(i=pre[t];i!=-1;i=pre[e[i].u]){
if(e[i].f<minf)
minf=e[i].f;
}
flow+=minf; //该条路径的流量
for(i=pre[t];i!=-1;i=pre[e[i].u]){
j=i^1;
e[i].f-=minf;
e[j].f+=minf;
}
cost+=dis[t]*minf; //单位运费和乘以流量得费用
}
printf("%d\n",cost);
}
int main(){
int i,u,v,c,n,m;
while(scanf("%d%d",&n,&m)==2){
t=0;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++){
scanf("%d%d",&u,&v);
add(0,i,0,1);
add(i,u+n,0,1);
add(i,v+n,0,1);
}
for(int i=1 ; i<=m ; ++i){
for(int j=1 ; j<=99 ; j+=2){//99 = 2*50-1;
add(i+n,n+m+1,j,1);
}
}
solve(0,n+m+1);
}
return 0;
}

B: Board

时间限制: 1 Sec  内存限制: 256 MB

题目描述

恬恬有一个n × n的数组。她在用这个数组玩游戏:

开始时,数组中每一个元素都是0。

恬恬会做某些操作。在一次操作中,她可以将某一行的所有元素同时加上一个值,也可以将某一列的所有元素同时加上一个值。

在几次操作后,一个元素被隐藏了。你能帮助她回忆隐藏的数是几吗?

输入

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

接下来n行每行n个整数表示数组a

第(i + 1)行的第j个元素表示aijaij =  - 1或0 ≤ aij ≤ 10000)。 - 1表示隐藏的元素。

输出

仅一个整数表示答案。

样例输入

3
1 2 1
0 -1 0
0 1 0

样例输出

1

这题思路同样为wls大佬给出,Orz wls 。。。

把格子N染色,第i行第j列格子的颜色为(i + j) % N。那么每次操作时,必定是N种不同的颜色都有一格被操作到,

因此最后任何颜色格子的和必定是相等的。因此只需要记录每种颜色格子的和,

并算出缺失格子的颜色C,用其余颜色的和减去颜色C的和即可

#include<bits/stdc++.h>

using namespace std;
int arr[1010][1010];
int a[1010], b[1010]; int main()
{
int n;
while(~scanf("%d", &n)){
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
int maxn = 10010, x, y;
for(int i = 1; i <= n; i++) {
maxn = 10010;
for(int j = 1; j <= n; j++) {
scanf("%d", &arr[i][j]);
if(arr[i][j] != -1){
maxn = min(maxn, arr[i][j]);
}
if(arr[i][j] == -1) {
x = i;
y = j;
}
}
a[i] = maxn;
}
int maxm;
for(int i = 1; i <= n; i++) {
int maxm = 10010;
for(int j = 1; j <= n; j++) {
if(arr[j][i] != -1){
maxm = min(maxm, arr[j][i]);
}
}
b[i] = maxm;
}
if(x == 1 && y == 1)cout << (a[x] + b[y]) - max((a[x+1]+b[y] - arr[x+1][y]),(a[x]+b[y+1]-arr[x][y+1])) << endl;
else if(x==n && y==1)cout << (a[x] + b[y]) - max((a[x-1]+b[y] - arr[x-1][y]),(a[x]+b[y+1]-arr[x][y+1])) << endl;
else if(x==1&&y==n)cout << (a[x] + b[y]) - max((a[x]+b[y-1] - arr[x][y-1]),(a[x+1]+b[y]-arr[x+1][y])) << endl;
else if(x==n&&y==n)cout << (a[x] + b[y]) - max((a[x-1]+b[y] - arr[x-1][y]),(a[x]+b[y-1]-arr[x][y-1])) << endl;
else if(x==1)cout << (a[x] + b[y]) - (a[x+1]+b[y]-arr[x+1][y]) << endl;
else if(x==n)cout << (a[x] + b[y]) - (a[x-1]+b[y]-arr[x+1][y]) << endl;
else cout << (a[x] + b[y]) - (a[x+1]+b[y] - arr[x+1][y]) << endl;
}
return 0;
}

D: Growth

时间限制: 1 Sec  内存限制: 256 MB

题目描述

弱弱有两个属性ab,这两个属性初始的时候均为0,每一天他可以通过努力,让a涨1点或b涨1点。

为了激励弱弱努力学习,我们共有n种奖励,第i种奖励有xiyizi三种属性,若axibyi,则弱弱在接下来的每一天都可以得到zi的分数。

问m天以后弱弱最多能得到多少分数。

输入

第一行一个两个整数nm(1 ≤ n ≤ 1000,1 ≤ m ≤ 2000000000)。

接下来n行,每行三个整数xiyizi(1 ≤ xi, yi ≤ 1000000000,1 ≤ zi ≤ 1000000)。

输出

一行一个整数表示答案。

样例输入

2 4
2 1 10
1 2 20

样例输出

50

提示

在样例中,弱弱可以这样规划:第一天a涨1,第二天b涨1,第三天b涨1,第四天a涨1。

共获得0 + 0 + 20 + 30 = 50分。

Orz wls。。。

把奖励的x拿出来从小到大排序,得到x1,x2,...,xn。

把奖励的y拿出来从小到大排序,得到y1,y2,...,yn。

用v[i][j]表示a值到达xi,b值达到yi时接下来每天可以得到的奖励。

v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + t[i][j]

其中t[i][j]为满足x=i,y=j的奖励的总和。

用f[i][j]表示a值达到xi,b值达到yj时已经拿到的奖励的最大值。

f[i][j] + (x[i + 1] - x[i] - 1) * t[i][j] + t[i + 1][j] -> f[i + 1][j]

f[i][j] + (y[j + 1] - y[j] - 1) * t[i][j] + t[i][j + 1] -> f[i][j + 1]

最后统计一下答案就可以了。

不过这题有一个离散化不好写,我也是借鉴大佬的写法,

#include<bits/stdc++.h>
using namespace std; #define ios1 ios::sync_with_stdio(0)
#define ios2 cin.tie(0)
#define ll long long
#define inf 0x7ffffffff
typedef pair<int, int> P;
map<P, int>mp;
set<int>sx, sy; const int maxn = 1200; int n, m;
int xx[maxn], yy[maxn];
ll dp[maxn][maxn], v[maxn][maxn];
int x[maxn], y[maxn], z[maxn]; int main() {
ios1; ios2;
while(cin >> n >> m) {
int xi = 1, yi = 1;
for(int i = 0; i < n; i++) {
cin >> x[i] >> y[i] >> z[i];
if(mp.count(P(x[i], y[i])) == 0)mp[P(x[i], y[i])] = z[i];
else mp[P(x[i], y[i])] += z[i];
if(sx.count(x[i]) == 0){sx.insert(x[i]);xx[xi++] = x[i];}
if(sy.count(y[i]) == 0){sy.insert(y[i]);yy[yi++] = y[i];}
}
sort(xx, xx + xi);
sort(yy, yy + yi);//离散化
memset(dp, 0, sizeof(dp));
memset(v, 0, sizeof(v));
for(int i = 1; i < xi; i++) {
for(int j = 1; j < yi; j++) {
if(mp.count(P(xx[i], yy[j])) == 0)v[i][j] = v[i-1][j] + v[i][j-1] - v[i-1][j-1];
else v[i][j] = v[i-1][j] + v[i][j-1] - v[i-1][j-1] + mp[P(xx[i], yy[j])];
}
}
for(int i = 0; i < xi; i++) {
for(int j = 0; j < yi; j++) {
dp[i+1][j] = max(dp[i+1][j], dp[i][j] + (xx[i+1] - xx[i] - 1) * v[i][j] + v[i+1][j]);
dp[i][j+1] = max(dp[i][j+1], dp[i][j] + (yy[j+1] - yy[j] - 1) * v[i][j] + v[i][j+1]);
}
}
ll ans = 0;
for(int i = 1; i < xi; i++) {
for(int j = 1; j < yi; j++) {
ll r = dp[i][j] + (m - xx[i] - yy[j]) * v[i][j];
ans = max(ans, r);
}
}
cout << ans << endl;
}
return 0;
}

最新文章

  1. Oracle 英文 非标准格式 日期 格式化
  2. Python 文件编码(文件乱码)
  3. Spark-1.0.0 standalone分布式安装教程
  4. spring加载hibernate映射文件的几种方式 (转)
  5. 洛谷P2727 01串 Stringsobits
  6. codeforces 687C - The Values You Can Make 简单dp
  7. 7 Hbase put方式插入数据
  8. .NET基础拾遗(1)类型语法基础和内存管理基础1
  9. 【Swift】学习笔记(四)——设置(Collection)
  10. 【Python3之模块及包的导入】
  11. python基础概念(转)
  12. XMLHttpRequest.withCredentials 解决跨域请求头无Cookie的问题
  13. IBase&lt;T&gt;
  14. Linux操作汇总
  15. BeautifuSoup的使用
  16. webpy 解决中文出现UnicodeDecodeError: &#39;ascii&#39; codec can&#39;t decode byte 问题
  17. JavaScript浏览器历史的语法小问题
  18. gcd和lcm模板
  19. 微信小程序获取当前位置
  20. 洛谷 P3749: LOJ 2146: [SHOI2017]寿司餐厅

热门文章

  1. Kafka消息队列初识
  2. 如何创建Github创库
  3. 论文阅读 | Falcon: Balancing Interactive Latency and Resolution Sensitivity for Scalable Linked Visualizations
  4. 从boosting谈起
  5. 大厂面试Kafka,一定会问到的幂等性
  6. Linux fuser工具使用方法介绍
  7. CSS动效集锦,视觉魔法的碰撞与融合(一)
  8. nginx单机1w并发优化
  9. SpringBoot打包部署简单说明
  10. Debian下Hadoop 3.12 集群搭建