想法:贪心。

A.最大高度大的先剪

首先需要知道:

1.每个草最多剪1次

假设有个草剪了2次,显然可以放到最后一次剪得效果和剪2次的效果一样的,

为了少剪那么草最多剪去一次,从而,步数step>N就是impossible!

所以枚举步数,每次从后往前贪心取最大的高度,后剪

code 70pts:

# include <bits/stdc++.h>
using namespace std;
const int MAXN=;
bool cut[MAXN];
int g[MAXN],h[MAXN],r[MAXN],u[MAXN],n,H;
bool check(int step)
{
memcpy(r,h,sizeof(h));
u[]=;
for (int i=;i<=n;i++) r[i]+=step*g[i];
memset(cut,false,sizeof(cut));
for (int i=;i<=step;i++) {
int MAX=,P;
for (int j=;j<=n;j++)
if (r[j]>MAX&&cut[j]==false) MAX=r[j],P=j;
u[++u[]]=P;
cut[P]=true;
}
for (int i=;i<=step/;i++) swap(u[i],u[step-i+]);
memcpy(r,h,sizeof(h));
for (int i=;i<=step;i++) {
for (int j=;j<=n;j++) r[j]+=g[j];
r[u[i]]=;
int sum=;
for (int j=;j<=n;j++) sum+=r[j];
if (sum<=H) return true;
}
int sum=;
for (int i=;i<=n;i++) sum+=r[i];
if (sum<=H) return true;
else return false;
}
int main()
{
freopen("grass.in","r",stdin);
freopen("grass.out","w",stdout);
int T;scanf("%d",&T);
while (T--) {
scanf("%d%d",&n,&H);
for (int i=;i<=n;i++) scanf("%d",&h[i]);
for (int i=;i<=n;i++) scanf("%d",&g[i]);
int ans=-;
for (int i=;i<=n;i++)
if (check(i)) { ans=i; break; }
printf("%d\n",ans);
}
return ;
}

反例:

input:

3 6

12 1 1

1 4 4

output:

3
WA:

-1

100pts DP!!!

就是找出这样2条规律:

2.长得快的最后剪

这是显然的,如果长得快的先剪那么在后面剪一次长得慢的时候长得快的还在生长,

F[i][j]前i棵草,剪去j棵(此时过了j天),最大剪去高度

F[i][j]转移:

第i棵草剪去,F[i-1][j-1]+h[i] +g[i]*j //i-1棵剪去j-1棵加上这时候草的高度先长后剪H‘ = h[i]+g[i]*j

第i棵草不剪,F[i-1][j] 没有多余动作

方程: f[i][j]=max(f[i-1][j],f[i-1][j-1]+h[i]+g[i]*j);

AC code

# include <bits/stdc++.h>
# define Rint register int
using namespace std;
const int MAXN=;
int h[MAXN],g[MAXN],f[MAXN][MAXN];
int read()
{
int r=,num=; char ch=getchar();
if (ch=='-') ch=getchar(),r=-;
while (isdigit(ch)) num=num*+ch-'',ch=getchar();
return num*r;
}
int main()
{
freopen("grass.in","r",stdin);
freopen("grass.out","w",stdout);
int T=read();
while (T--) {
int n=read(),H=read();
int sumh=,sumg=;
for (Rint i=;i<=n;i++) h[i]=read(),sumh+=h[i];
for (Rint i=;i<=n;i++) g[i]=read(),sumg+=g[i];
memset(f,,sizeof(f));
for (Rint i=;i<=n-;i++)
for (Rint j=i+;j<=n;j++)
if (g[i]>g[j]) swap(g[i],g[j]),swap(h[i],h[j]);
for (Rint i=;i<=n;i++)
for (Rint j=;j<=i;j++)
f[i][j]=max(f[i-][j],f[i-][j-]+h[i]+g[i]*j);
int ans=-;
for (Rint i=;i<=n;i++)
if (sumh+sumg*i-f[n][i]<=H) { ans=i; break; }
printf("%d\n",ans);
}
return ;
}

Hint:题目出错:最后的条件改为A[i]-x<=B[j]<=A[i]+y;

想法:

50pts二分图匹配,按照题意模拟建边,匈牙利算法O(n2)轻松跑过

100pts运用单调性,知道A,B两个序列都是有序的,而x和y都是定值那么

满足的条件: A[i](单调递增) B[j](单调递增)

当B[j]不满足A[i]限制1的时候( B[j]>A[i]+y )B[j+1] 到B[m]都不符合

当B[j]不满足A[i]限制2的时候(B[j]<A[i]-x) B[1]到B[j]都不符合

那么贪心取最小的A[i]和B[j]就行

code 100pts (匈牙利和单调队列放一起了凑合着看看)

# include <bits/stdc++.h>
# define Rint register int
using namespace std;
const int MAXN=,MAXN2=;
bool mp[MAXN][MAXN],vis[MAXN];
int a[MAXN2],b[MAXN2],pre[MAXN];
int n,m,x,y,ans=;
bool find(int u)
{
for (Rint v=;v<=m;v++)
if (mp[u][v]&& !vis[v]) {
vis[v]=;
if (pre[v]==-||find(pre[v])) {
pre[v]=u;
return ;
}
}
return ;
}
void solve()
{
memset(pre,-,sizeof(pre));
for (Rint i=;i<=n;i++) {
memset(vis,false,sizeof(vis));
if (find(i)) ans++;
}
}
void work()
{
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<=m;i++) scanf("%d",&b[i]);
int i=,j=,ans=;
while (true) {
while (b[j]<a[i]-x&&j<=m) j++;
if (i>n||j>m) break;
if (b[j]<=a[i]+y) ans++,j++;
if (i>n||j>m) break;
i++;
}
printf("%d\n",ans);
}
int main()
{
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&x,&y);
if (n>MAXN) { work();return ; }
for (Rint i=;i<=n;i++) scanf("%d",&a[i]);
for (Rint i=;i<=m;i++) scanf("%d",&b[i]);
memset(mp,sizeof(mp),false);
for (Rint i=;i<=n;i++)
for (Rint j=;j<=m;j++)
if (a[i]-x<=b[j]&&b[j]<=a[i]+y) mp[i][j]=true;
solve();
printf("%d\n",ans);
return ;
}

【APIO2013】hahahahaha做什么?

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm> using namespace std; const int N = , M = , K = ; int n, m, k, cn = ;
long long ans = , maxL, ssize;
int cost[N], father[N], color[N];
long long size[N] = {}; long long get_max(long long a, long long b)
{
if (a > b) return a; else return b;
}
long long get_min(long long a, long long b)
{
if (a < b) return a; else return b;
} class Road
{
public :
int x, y, w, flag, ans;
Road (int x, int y, int w = , int flag = )
: x(x), y(y), w(w), flag(flag) {}
}; Road * road[M],
* road_sp[K]; class Node; class Edge
{
public :
Node * target;
Edge * next;
int flag;
/*Edge(Node * target, Edge * next, int flag) :
target(target), next(next), flag(flag) {};
~Edge()
{
if (next) delete next;
}*/
}; class Node
{
public :
Edge * head;
Node * father;
long long size, deep, flag;
/*
Node (long long size) :
size(size), head(0), father(0), deep(0), flag(0) {}
~Node()
{
if (head) delete head;
}
*/
}; Node * node[K]; Node * my_node[]; int my_node_count;
Edge * my_edge[]; int my_edge_count; Node * get_node(long long size)
{
Node * now = my_node[my_node_count ++];
now->size = size;
now->head = ;
now->father = ;
now->deep = ;
now->flag = ;
return now;
} Edge * get_edge(Node * target, Edge * next, int flag)
{
Edge * now = my_edge[my_edge_count ++];
now->target = target;
now->next = next;
now->flag = flag;
return now;
} void newedge(Node * x, Node * y, int flag)
{
Edge * e1 = get_edge(y, x->head, flag),
* e2 = get_edge(x, y->head, flag);
x->head = e1; y->head = e2;
} bool cmp_w(const Road * a, const Road * b)
{return a->w < b->w;} void init()
{
for (int i=; i<; i++)
{
my_edge[i] = new Edge();
my_node[i] = new Node();
}
scanf("%d%d%d", &n, &m, &k);
int x, y, w;
for (int i=; i<m; i++)
{
scanf("%d%d%d", &x, &y, &w);
road[i] = new Road(x, y, w);
}
for (int i=; i<k; i++)
{
scanf("%d%d", &x, &y);
road_sp[i] = new Road(x, y);
}
for (int i=; i<=n; i++)
scanf("%d", cost+i);
} int get_father(int x)
{
int head = x;
while (father[head] != head) head = father[head];
while (x != head)
{
int tmp = father[x];
father[x] = head;
x = tmp;
}
return head;
} void select()
{
sort(road, road+m, cmp_w);
for (int i=; i<=n; i++) father[i] = i;
for (int i=; i<m; i++)
{
int x = get_father(road[i]->x),
y = get_father(road[i]->y);
if (x != y)
{
road[i]->flag = ;
father[x] = y;
}
}
m = ;
for (int i=; m<n-; i++)
if (road[i]->flag) road[m++] = road[i];
} void check_select()
{
printf("m = %d\n", m);
for (int i=; i<m; i++)
printf("x = %d y = %d w = %d\n", road[i]->x, road[i]->y, road[i]->w);
} void build()
{
for (int i=; i<=n; i++) father[i] = i;
for (int i=; i<k; i++)
{
int x = get_father(road_sp[i]->x),
y = get_father(road_sp[i]->y);
if (x != y) father[x] = y;
}
for (int i=; i<m; i++)
{
int x = get_father(road[i]->x),
y = get_father(road[i]->y);
if (x != y)
father[x] = y;
else
road[i]->flag = ;
}
for (int i=; i<=n; i++) father[i] = i;
for (int i=; i<m; i++)
if (road[i]->flag)
{
int x = get_father(road[i]->x),
y = get_father(road[i]->y);
father[x] = y;
}
for (int i=; i<=n; i++)
if (father[i] == i)
color[i] = cn++;
for (int i=; i<=n; i++)
{
color[i] = color[get_father(i)];
size[color[i]] += cost[i];
}
m = ;
for (int i=; i<n-; i++)
if (!road[i]->flag) road[m++] = road[i];
} void check_build()
{
for (int i=; i<cn; i++)
{
printf("Color %d :", i);
for (int j=; j<=n; j++)
if (color[j] == i) printf("%d ", j);
printf(" size = %I64d\n", size[i]);
}
printf("sp edge:\n");
for (int i=; i<k; i++)
printf("x = %d y = %d\n", color[road_sp[i]->x], color[road_sp[i]->y]);
printf("other edge:\n");
for (int i=; i<m; i++)
printf("x = %d y = %d w = %d\n", color[road[i]->x], color[road[i]->y], road[i]->w);
} long long work(Node * & x, int w)
{
long long s = ;
if (x->flag)
{
//road_sp[x->flag-1]->ans = w;
s = x->size * w;
x->flag = ;
ssize -= x->size;
}
x = x->father;
return s;
} void dfs(Node * now)
{
for (Edge * e = now->head; e!=; e=e->next)
{
if (!e->target->deep)
{
e->target->deep = now->deep + ;
e->target->flag = e->flag;
e->target->father = now;
dfs(e->target);
if (e->flag) ssize += e->target->size;
now->size += e->target->size;
}
}
} void clear_road_sp()
{
for (int i=; i<k; i++) road_sp[i]->ans = ;
} void print_road_sp(long long s)
{
return ;
printf("%I64d ", s);
for (int i=; i<k; i++) printf("%d ", road_sp[i]->ans);
printf("\n", s);
} long long get_ans()
{
my_node_count = ;
my_edge_count = ;
for (int i=; i<cn; i++) node[i] = get_node(size[i]);
for (int i=; i<cn; i++) father[i] = i;
for (int i=; i<k; i++)
if (road_sp[i]->flag)
{
int x = get_father(color[road_sp[i]->x]),
y = get_father(color[road_sp[i]->y]);
if (x == y) return ;
father[x] = y;
newedge(node[color[road_sp[i]->x]], node[color[road_sp[i]->y]], i+);
}
maxL = ;
for (int i=; i<m; i++)
{
int x = get_father(color[road[i]->x]),
y = get_father(color[road[i]->y]);
if (x != y)
{
road[i]->flag = ;
father[x] = y;
newedge(node[color[road[i]->x]], node[color[road[i]->y]], );
}
else
{
if (road[i]->w > maxL) maxL = road[i]->w;
road[i]->flag = ;
}
} node[color[]]->deep = ;
ssize = ;
dfs(node[color[]]);
long long s = ;
//clear_road_sp();
for (int i=; i<m; i++)
{
if (ssize * maxL + s < ans) break;
if (road[i]->flag)
{
Node * x = node[color[road[i]->x]],
* y = node[color[road[i]->y]];
int c = ;
while (x != y)
if (x->deep > y->deep) s += work(x, road[i]->w); else s += work(y, road[i]->w);
}
}
//if (ssize != 0) printf("A = %I64d\n", ssize);
//print_road_sp(s);
for (int i=; i<=cn; i++) delete node[i];
return s;
} void dfs(int now)
{
if (now == k)
{
ans = get_max(get_ans(), ans);
return ;
}
road_sp[now]->flag = ;
dfs(now+);
road_sp[now]->flag = ;
dfs(now+);
} int main()
{
freopen("toll.in", "r", stdin);
freopen("toll.out", "w", stdout);
init();
select();
//check_select();
build();
//check_build();
dfs(); cout << ans << endl;
return ;
}

最新文章

  1. DDD 领域驱动设计-领域模型中的用户设计
  2. OpenCASCADE Curve Length Calculation
  3. JS正则大全
  4. Android test---monkey
  5. 我的conky配置
  6. &lt;转&gt;HTML中的table转为excel
  7. Android基础问题汇总
  8. linux查看系统版本
  9. Spring mvc基本原理
  10. 打通MySQL的操作权限
  11. Hibernate学习(一)创建数据表
  12. 中断处理程序不能使用printf的本质
  13. Linux学习之文件系统权限及表示
  14. numpy鸢尾花
  15. python day07笔记总结
  16. 区分defer和async
  17. linux安装jdk与配置-centos7版本
  18. 【Android】Android如何对APK反编译
  19. ngRoute 与ui.router区别
  20. kindEditor富文本编辑器

热门文章

  1. python基础3之文件操作、字符编码解码、函数介绍
  2. 20155232《网络对抗》Exp5 MSF基础应用
  3. 20155318 Exp1 PC平台逆向破解(5)M
  4. 20155323刘威良《网络对抗》Exp6 信息搜集与漏洞扫描
  5. JavaEE笔记(十三)
  6. JavaScript闭包简单应用
  7. asp.net web api参数
  8. 2014.8.23 Research Meeting Report
  9. 2018-07-09--记录一次gitlab迁移事件及遇到的问题
  10. unity小地图制作___按比例尺图标布局