E. Kojiro and Furrari
题意说的是 在一条直线上 有n个加油站, 每加一单位体积的汽油 可以走1km 然后每个加油站只有一种类型的汽油,汽油的种类有3种 求从起点出发到达终点要求使用最少的 1 号汽油的前提下使用最少的二号汽油,
我们可以这样考虑
当前在第i个加油站的时候         i个加油站 有3种情况
第一种 他是只有 1 号汽油 那么他必须携带 尽量少的 1号汽油到达离他最近的2号汽油点或者3号汽油点 更新这个点到达终点的代价 取最小值,因为他必须通过那个点到达其他点
第二种 他只有 2 号汽油, 那么他必须携带 尽量多的 2号汽油到达能达到的最远的1号汽油点,这样可以更少使用1号汽油,或者 带尽量少的汽油到达离他最近的3号汽油的点,或者最近的2号汽油的点
第三种 如果他是3号汽油 那么他必须携带尽量少的3号汽油到达离他最近的点,或者带尽量多的3号汽油到达离他能达到的最远的1 、2号汽油点
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn=;
const int INF=;
struct point{
int x,t;
point(int cx=, int ct=){
x=cx; t=ct;
}
bool operator <(const point &rhs)const{
return x<rhs.x;
}
}P[maxn];
int D[][maxn],num[];
int dp[maxn][];
int e,s,n,m;
int bitlook1(int x,int *C, int n)
{
int L=,R=n-,ans=-;
while(L<=R)
{
int mid=(L+R)>>;
int id=C[mid];
if( P[id].x>=x ){
ans=mid;
R=mid-;
}else{
L=mid+;
}
}
return ans;
}
void cmp(int &A, int &B,int &V, int C, int D, int DV)
{
if(A>=C){
if(A==C){
if(B<D) return ;
if(B>D){
B=D;
V=DV;
}else{
V=min(V,DV);
}
}
else {
A=C; B=D;
V=DV;
}
}
}
void solve1(int id)
{
int loc=P[id].x;
int d1=bitlook1(loc+,D[],num[]);
int d2=bitlook1(loc+,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1];
if( d3!=- && P[d3].x <= loc+s )
{
int cp1 = dp[d3][]+P[d3].x-loc;
int cp2 = dp[d3][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d3].x-loc);
}
if(d2!=- && P[d2].x<=loc+s)
{
int cp1 = dp[d2][]+P[d2].x-loc;
int cp2 = dp[d2][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d2].x-loc);
}
if( d1!=- && P[d1].x<=loc+s)
{
int cp1 = dp[d1][]+P[d1].x-loc;
int cp2 = dp[d1][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d1].x-loc);
}
}
int bitlook2(int x,int *C, int n)
{
int L=,R=n-,ans=-;
while(L<=R)
{
int mid=(L+R)>>;
int id=C[mid];
if( P[id].x<=x ){
ans=mid;
L=mid+;
}else{
R=mid-;
}
}
return ans;
}
void solve2(int id)
{
int loc=P[id].x;
int d1=bitlook2(loc+s,D[],num[]);
int d2=bitlook1(loc+,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1];
if( d3!=- && P[d3].x <= loc+s )
{
int cp1 = dp[d3][];
int cp2 = dp[d3][]+P[d3].x-loc;
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d3].x-loc);
}
if(d2!=- && P[d2].x<=loc+s)
{
int cp1 = dp[d2][];
int cp2 = dp[d2][]+P[d2].x-loc;
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d3].x-loc);
} if( d1!=-&&P[d1].x>loc)
{
int cp0=s;
int lit = s-(P[d1].x-loc);
int cp1 = dp[d1][]-min(lit,dp[d1][]);
int cp2 = dp[d1][]+cp0;
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,cp0);
}
}
void solve3(int id)
{
int loc=P[id].x;
int d1=bitlook2(loc+s,D[],num[]);
int d2=bitlook2(loc+s,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1]; if( d3!=- && P[d3].x<=loc+s )
{
cmp(dp[id][],dp[id][],dp[id][],dp[d3][],dp[d3][],);
}
if(d2!=-&&P[d2].x>loc)
{
int lit = s-(P[d2].x-loc);
int cp1 = dp[d2][];
int cp2 = dp[d2][]-min(dp[d2][],lit);
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,);
}
if(d1!=-&&P[d1].x>loc)
{
int lit = s-(P[d1].x-loc);
int cp1 = dp[d1][]-min(dp[d1][],lit);
int cp2 = dp[d1][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,);
}
}
void solve4(int loc, int &S1,int &S2)
{
int k;
int d1=bitlook2(loc+s,D[],num[]);
int d2=bitlook2(loc+s,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1];
if( d3!=- && P[d3].x<=loc+s &&dp[d3][]!=INF)
{
cmp(S1,S2,k,dp[d3][],dp[d3][],);
}
if(d2!=-&&P[d2].x>loc&&dp[d2][]!=INF)
{
int lit = s-(P[d2].x-loc);
int cp1 = dp[d2][];
int cp2 = dp[d2][]-min(dp[d2][],lit);
cmp(S1,S2,k,cp1,cp2,);
}
if(d1!=-&&P[d1].x>loc&&dp[d1][]!=INF)
{
int lit = s-(P[d1].x-loc);
int cp1 = dp[d1][]-min(dp[d1][],lit);
int cp2 = dp[d1][];
cmp(S1,S2,k,cp1,cp2,);
}
}
int main()
{
while(scanf("%d%d%d%d",&e,&s,&n,&m)==)
{
num[]=num[]=num[]=num[]=;
int k=;
for(int i=; i<n; i++) {
scanf("%d%d",&P[k].t,&P[k].x);
if(P[k].x<e)k++;
}
n=k;
sort(P,P+n);
if(P[n-].x!=e)
{
P[n]=point(e,);
n++;
}
for(int i=; i<n; i++)
if(P[i].t==) D[ ][num[]++ ] =i;
else if(P[i].t==) D[][ num[] ++ ]=i;
else D[][ num[]++ ]=i;
dp[n-][]=dp[n-][]=dp[n-][]=;
for(int i=n-; i>=;i--)dp[i][]=dp[i][]=dp[i][]=INF; for(int i=n-; i>=; i--)
{
if(P[i].t==)solve1(i);
else if(P[i].t==)solve2(i);
else solve3(i);
if(dp[i][]==INF)break;
}
for(int i=;i<m; i++)
{
int S1=INF,S2=INF;
int loc;
scanf("%d",&loc);
solve4(loc,S1,S2);
if(S1==INF){
printf("-1 -1\n");
}else{
printf("%d %d\n",S1,S2);
}
}
}
return ;
}
/*
386 20 1 1
2 369
351 */

F. Zublicanes and Mumocrates 树形dp

题意给了一棵树 要求使得这棵树所有的节点分为两个阵营,其中叶子节点要均分,求最少的两个阵营相邻, 也就是求 最少的边使得 这些边两头阵营不同

dp[cur][i][j] 表示当cur为i阵营的时候 有j个和i同阵营的方案

dp[cur][i][j+k] = min{dp[to][i^1][j=(叶子个数-d)]+dp[cur][i][k]+1,dp[to][i][j]+dp[cur][i][k]}

cnt为叶子节点的个数 最后答案是 min{ dp[root][0][cnt/2] ,dp[root][1][cnt/2]}

#include <algorithm>
#include <string.h>
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn=;
int H[maxn],to[maxn*],nx[maxn*],numofE;
void add(int u, int v)
{
numofE++;
to[numofE]=v;
nx[numofE]=H[u];
H[u]=numofE;
}
int dp[maxn][][maxn];
int dp2[][maxn],sz[maxn];
int d[maxn];
void dfs(int cur ,int per)
{
if(d[cur]==){
sz[cur]=;
dp[cur][][]=dp[cur][][]=;
return ;
}
dp[cur][][]=dp[cur][][]=;
for(int i=H[cur]; i ; i=nx[i])
{
int tto = to[i];
if(tto==per)continue;
dfs(tto,cur);
for(int i=; i<=sz[cur]; i++)
for(int u=; u<; u++)
{
if( dp[cur][u][i] == - ) continue; for(int j=; j<=sz[tto]; j++)
for(int v=; v<; v++)
{
if(dp[tto][v][j]==-)continue;
if(u==v)
{
if(dp2[u][i+j]==-)
{
int k=dp[cur][u][i]+dp[tto][v][j];
dp2[u][i+j] = k; }else {
int k=min(dp[cur][u][i]+dp[tto][v][j],dp2[u][i+j]);
dp2[u][i+j]=k; }
}else
{
int nu=sz[tto];
if(dp2[u][i+nu-j]==-)
{
int k=dp[cur][u][i]+dp[tto][v][j]+;
dp2[u][i+nu-j]=k;
}
else
{
int k=min(dp[cur][u][i]+dp[tto][v][j]+,dp2[u][i+nu-j]);
dp2[u][i+nu-j]=k; }
}
}
}
sz[cur]+=sz[tto];
for(int i=; i<=sz[cur]; i++)
for(int j=; j<; j++)
{
dp[cur][j][i]=dp2[j][i];
dp2[j][i]=-;
}
}
}
int main()
{
int n;
while(scanf("%d",&n)==)
{
memset(d,,sizeof(d));
memset(dp,-,sizeof(dp));
memset(sz,,sizeof(sz));
memset(dp2,-,sizeof(dp2));
memset(H,,sizeof(H));
numofE=;
for(int i=; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
d[a]++;d[b]++;
}
if(n==){
printf("%d\n",); continue;
}
int root;
int cnt=;
for(int i=; i<=n; i++){
if(d[i]==)cnt++;
else root=i;
}
dfs(root,-);
printf("%d\n",min(dp[root][][cnt/],dp[root][][cnt/]));
}
return ;
}
/*
6
1 2
2 5
2 3
3 4
3 6
*/

Codeforces Round #322 (Div. 2) E F的更多相关文章

  1. Codeforces Round #573 (Div. 1) 差F

    Codeforces Round #573 (Div. 1) E 题意:二维平面上有 n 个点,你可以放至多 m 条直线使得 (0,0) 与每个点的连线至少与一条直线相交.求原点与所有直线的距离最小值 ...

  2. Codeforces Round #322 (Div. 2) —— F. Zublicanes and Mumocrates

    It's election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The ...

  3. 树形dp - Codeforces Round #322 (Div. 2) F Zublicanes and Mumocrates

    Zublicanes and Mumocrates Problem's Link Mean: 给定一个无向图,需要把这个图分成两部分,使得两部分中边数为1的结点数量相等,最少需要去掉多少条边. ana ...

  4. Codeforces Round #322 (Div. 2) D. Three Logos 暴力

    D. Three Logos Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/problem ...

  5. Codeforces Round #322 (Div. 2) C. Developing Skills 优先队列

    C. Developing Skills Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/p ...

  6. Codeforces Round #322 (Div. 2) B. Luxurious Houses 水题

    B. Luxurious Houses Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/pr ...

  7. Codeforces Round #322 (Div. 2) A. Vasya the Hipster 水题

    A. Vasya the Hipster Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/p ...

  8. Codeforces Round #541 (Div. 2) (A~F)

    目录 Codeforces 1131 A.Sea Battle B.Draw! C.Birthday D.Gourmet choice(拓扑排序) E.String Multiplication(思路 ...

  9. Codeforces Round #532 (Div. 2):F. Ivan and Burgers(贪心+异或基)

    F. Ivan and Burgers 题目链接:https://codeforces.com/contest/1100/problem/F 题意: 给出n个数,然后有多个询问,每次回答询问所给出的区 ...

随机推荐

  1. 转:centos7/rhel7安装较高版本ruby2.2/2.3/2.4+

    centos7/rhel7安装较高版本ruby2.2/2.3/2.4+   环境需求:  在Centos7.3中,通过yum安装ruby的版本是2.0.0,但是如果有些应用需要高版本的ruby环境,比 ...

  2. 《linux 用户管理》- useradd/userdel/usermod/groupadd/who/w

    一:概念 在 Linux 中,使用一个 32位整数 来记录每一个用户(USER ID 简单 UID),这意味着在 Linux 中,可以有 40亿 个不同的用户. 系统. 在 /etc/passwd  ...

  3. file 选取文件/文件夹

    一般网页上传文件大家都会用到这个标签 <input type="file" id="file_input"/> 我们可以通过这个标签选取文件,使用j ...

  4. MyEclipse下创建的项目 导入eclipse

    1.导入在MyEclipse下创建的项目 2.把项目变成Web项目,在项目上右键-->Properties-->选择Project Facets-->点击Convert to fac ...

  5. (4.6)mysql备份还原——深入解析二进制日志(2)binlog参数配置解析

    关键词:binlog配置,binlog参数,二进制日志配置,二进制文件参数配置 关键词:binlog缓存,binlog 刷新 0.bin写入流程 写binlog流程如下:# 数据操作buffer po ...

  6. (1.9)SQL优化——mysql导入导出优化

    (1.9)SQL优化——mysql导入导出优化 1.大批量插入数据 [1.1]MyISAM: (1)如果存在表且有数据,插入前先关闭所有非唯一索引. (2)如果表是空的,默认就是先导入数据再创建索引, ...

  7. open():打开文件

    1.open():使用指定的模式和编码打开文件,返回文件读写对象 2.使用说明: (1)使用格式:open(filename [, mode [, bufsize]])(2)打开一个文件,返回一个fi ...

  8. 自动化工具之三:pywinauto

    Python自动化工具:pywinauto 一.pywinauto的安装 (1)安装命令 pip install -U pywinauto/pip3 install -U pywinauto (2)验 ...

  9. git命令操作的时候,出现中文名显示问题

    方法一:git config --global core.quotepath false 方法二: Windows系统的Git默认是不支持中文显示的,需要进行一系列的设置才能避免乱码的出现,下面总结如 ...

  10. tf实现LSTM时rnn.DropoutWrapper

    转自:https://blog.csdn.net/abclhq2005/article/details/78683656 作者:abclhq2005 1.概念介绍 所谓dropout,就是指网络中每个 ...