1、给定一棵有根树,每个节点有一个权值(有正有负)。裁剪掉一些子树使得最后所有节点的权值和最大?
思路:$f[u][0],f[u][1]$表示$u$节点表示的子树去掉和不去掉节点$u$的最大权值。
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <assert.h>
using namespace std;
const int N=3005;
vector<int> g[N];
int n;
int a[N];
int f[N][2];
void dfs(int u)
{
f[u][0]=0;
f[u][1]=a[u];
for(int i=0;i<(int)g[u].size();++i)
{
int v=g[u][i];
dfs(v);
f[u][1]+=max(f[v][0],f[v][1]);
}
}
class FiringEmployees
{
public:
int fire(vector<int> manager,vector<int> salary,vector<int> productivity)
{
n=(int)manager.size();
for(int i=0;i<n;++i) {
g[manager[i]].push_back(i+1);
}
for(int i=1;i<=n;++i) {
a[i]=productivity[i-1]-salary[i-1];
}
dfs(0);
return f[0][1];
}
};
2、给定二维平面上$n$个蓝点和$m$个红点。任意三点不共线,任意两点不重合。选择一个凸包使其在不包含红点的前提下包含的蓝点尽可能多?输出最多的蓝点个数。$n,m \leq 50$
思路:首先预处理计算任意三个蓝点组成的三角形中的蓝点个数以及是否包含红点。凸包可以分割成三角形。首先初始化凸包的三个顶点为$x,y,z$(假设$x,y,z$是逆时针),然后每次增加一个新的点进来,设最后加入凸包的两个点为$p_{1},p_{2}$,新加入的点为$q$,那么$q$需要满足的条件为:
(1)三角形$x,p_{2},q$中没有红点;
(2)$q$在射线$x,p_{2}$的左侧;
(3)$q$在射线$p_{1},p_{2}$的左侧;
(4)$q$在射线$x,y$的左侧.
这样进行记忆化搜索即可。
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <assert.h>
using namespace std;
struct point
{
double x,y;
point(){}
point(double _x,double _y) {x=_x; y=_y;}
point operator+(point a) { return point(x+a.x,y+a.y); }
point operator-(point a) { return point(x-a.x,y-a.y); }
double operator*(point a) { return x*a.y-y*a.x; }
double operator^(point a) { return x*a.x+y*a.y; }
point operator*(double t) { return point(x*t,y*t); }
point operator/(double t) { return point(x/t,y/t); }
point verlLeft() { return point(-y,x); }
point verlRight() { return point(y,-x); }
void read() { scanf("%lf %lf",&x,&y);}
};
#define EPS 1e-12
int sgn(double x)
{
if(x>EPS) return 1;
if(x<-EPS) return -1;
return 0;
}
double cross(point a,point b,point p)
{
return (b-a)*(p-a);
}
int onLeft(point a,point b,point p)
{
return ((b-a)*(p-a))>0;
}
double getArea(point a,point b,point c)
{
return fabs(cross(a,b,c))*0.5;
}
int inside(point a,point b,point c,point d)
{
double s=getArea(a,b,c);
double S=getArea(a,b,d)+getArea(a,c,d)+getArea(b,c,d);
return sgn(s-S)==0;
}
const int N=55;
point p[N],q[N];
int n,m;
int dp[N][N][N];
int cal(point a,point b,point c)
{
double s=getArea(a,b,c);
for(int i=1;i<=m;++i)
{
double S=getArea(a,b,q[i])+getArea(a,c,q[i])+getArea(b,c,q[i]);
if(sgn(S-s)==0) return 1;
}
return 0;
}
int f[N][N][N];
struct node
{
int i,j,t,cnt;
node(){}
node(int _i,int _j,int _t,int _cnt):i(_i),j(_j),t(_t),cnt(_cnt) {}
};
queue<node> Q;
int inq[N][N][N];
int g[N][N][N];
int get(const int id)
{
memset(f,0,sizeof(f));
memset(inq,0,sizeof(inq));
while(!Q.empty()) Q.pop();
int ans=0;
for(int i=1;i<=n;++i) {
for(int j=1;j<=n;++j) {
if(i!=id&&i!=j&&j!=id&&!dp[id][i][j]&&onLeft(p[id],p[i],p[j])) {
f[i][i][j]=3+g[id][i][j];
ans=max(ans,f[i][i][j]);
inq[i][i][j]=1;
Q.push(node(i,j,i,f[i][i][j]));
}
}
}
while(!Q.empty())
{
node pp=Q.front(); Q.pop();
inq[pp.t][pp.i][pp.j]=0;
for(int i=1;i<=n;++i)
{
if(i==id||i==pp.i||i==pp.j||i==pp.t||dp[id][pp.j][i]) continue;
if(onLeft(p[pp.i],p[pp.j],p[i])
&&onLeft(p[id], p[pp.j],p[i])
&&onLeft(p[id], p[pp.t],p[i])) {
int sum=pp.cnt+1+g[pp.j][i][id];
if(f[pp.t][pp.j][i]<sum) {
f[pp.t][pp.j][i]=sum;
ans=max(ans,sum);
if(!inq[pp.t][pp.j][i]) {
inq[pp.t][pp.j][i]=1;
Q.push(node(pp.j,i,pp.t,sum));
}
}
}
}
}
return ans;
}
class RedAndBluePoints
{
public:
int find(vector<int> blueX,vector<int> blueY,vector<int> redX,vector<int> redY)
{
n=(int)blueX.size();
if(n<=2) return n;
for(int i=1;i<=n;++i) {
p[i]=point(blueX[i-1],blueY[i-1]);
}
m=(int)redX.size();
for(int i=1;i<=m;++i) {
q[i]=point(redX[i-1],redY[i-1]);
}
for(int i=1;i<=n;++i) {
for(int j=1;j<=n;++j) {
for(int k=1;k<=n;++k) {
if(i!=j&&i!=k&&j!=k) {
dp[i][j][k]=cal(p[i],p[j],p[k]);
for(int t=1;t<=n;++t) {
if(t!=i&&t!=j&&t!=k&&inside(p[i],p[j],p[k],p[t])) {
++g[i][j][k];
}
}
}
}
}
}
int ans=2;
for(int i=1;i<=n;++i)
{
ans=max(ans,get(i));
}
return ans;
}
};