T1 陪审团

题目

【题目描述】

陪审团制度历来是司法研究中的一个热议话题,由于陪审团的成员组成会对案件最终的结果产生巨大的影响,诉讼双方往往围绕陪审团由哪些人组成这一议题激烈争夺。小 W提出了一个甲乙双方互相制衡的陪审团成员挑选方法:假设共有 n 名候选陪审团成员,则由甲先提名 s 位候选人,再由乙在甲提名的 s 位候选人中选出t名,作为最终的陪审团成员。显然这里应当有 n≥s≥t 。假设候选人k对甲、乙的有利程度都可以用一个二元组( xk ,yk )来表示,x.越大说明候选人 k 对甲越有利, yk 越大则对乙越有利。在此前提下,双方的目标都变得明确:甲要最大化最终陪审团 t 人的 x 之和,最小化 y之和,乙则反之。
现在甲方决定聘请你为律师,并且事先得知了乙方律师的策略:乙方律师会在你提名的 s名候选人中选出 t 名使得这 t 人的 y 值之和最大,再保证 y 值之和最大的前提下使得 x值之和尽量小(在对乙方最有利的前提下对甲方最不利)。
现在你应当慎重地提名 s 位候选人使得最终由乙方律师确定的 t 人 x 值和最大,若有多种方案,则应再使被乙方排除掉的 t-s 人的 y 值和尽量大,在此基础上最大化 s 人的 x值之和。 你的当事人并不关心你提名的具体是哪些人,只要你告诉他你提名的s人的x值之和与y值之和。

【输入格式】

第一行包含三个整数n,s,t。
接下来nn行,每行两个整数分别表示xk,yk。

【输出格式】

共一行两个整数,分别为x值之和与y值之和。

【数据规模】

对于30%的测试数据n≤20
对于50%的测试数据n≤100
对于100%的测试数据n≤100000,x,y≤1000000

解析

因为乙会从s个中选出t个对自己有利的,所以剩下s-t个就是不选的,所以n个中一定至少有s-t个未被选中,这就是y最小的s-t个。

所以我们先按y的大小排序一遍,最后的s-t个假设我们先选了,乙就没有选择的余地了。

然后我们按x的大小排序一遍,这样我们可以保证自己得到的结果是最大的。

但到了这里还有一个漏洞,那就是s-t的要尽可能大(多个方案下)。因此我们将第一遍的t个选择标记,在按y的从大到小排序若y值相同,则x值小的在后面。这样从后往前先找到自己的第一个标记处,往后重新选择s-t个,这s-t个肯定是y比前面的小,但是最大的,且s的x之和是最大的。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; long long n,s,t,sumx,sumy; struct person{
int x,y;
bool cho;
}per[]; bool cmp1(person a,person b)
{
if(a.y==b.y) return a.x>b.x;
return a.y<b.y;
} bool cmp2(person a,person b)
{
if(a.x==b.x) return a.y>b.y;
return a.x>b.x;
} bool cmp3(person a,person b)
{
if(a.y!=b.y) return a.y>b.y;
if(a.x!=b.x) return a.x>b.x;
return ((int)(a.cho)-(int)(b.cho)>);
}
int read()
{
char ch;
bool flag=false;
int num=;
ch=getchar();
while(ch>''||ch<'')
{
if (ch=='-') flag=true;
ch=getchar();
}
while(ch>=''&&ch<='')
{
num=num*+(ch-'');
ch=getchar();
}
if (flag==true) num*=-;
return num;
} int main()
{
n=read(),s=read(),t=read();
for(int i=;i<=n;i++)
{
per[i].x=read();
per[i].y=read();
}
sort(per+,per+n+,cmp3);
sort(per+,per++n-s+t,cmp2);
for(int i=;i<=t;i++) per[i].cho=;
sort(per+,per+n+,cmp3);
int first;
for(int i=n;i>=;i--)
if(per[i].cho)
{
first=i;
break;
}
int i;
for(i=t+,first++;i<=s;i++,first++) per[first].cho=;
for(int i=;i<=n;i++)
if(per[i].cho)
{
sumx+=per[i].x;
sumy+=per[i].y;
}
cout<<sumx<<sumy;
return ;
}

T2 shine

题目

【题目描述】

今天是NOIP初赛,Capo坐在考场上看着手中的初赛试卷,非常无聊,早已被钦点进入复赛的她在卷子上做了奇怪的事。 卷子可以看成一张n×m的方格纸,Capo手中有一支笔头截面是x×y矩形的笔,她在试卷上画下了一道痕迹,痕迹是由笔在纸面上做平行网格的运动画出的,笔不可以旋转,刚开始笔头截面的边平行与网格,每次移动,笔头只会向下或者向右移动一格。 阅卷老师Octavia看到了这张卷子,他对Capo的笔十分好奇,于是他想从笔迹中猜出笔头截面大小,请你告诉他x×y的最小值。

【输入格式】

第一行两个整数n,m表示卷子大小。 下面n行,每行m个字符,X表示有笔迹,.表示没有。

【输出格式】

一行一个整数,表示最小的x×y,无解输出-1

【数据规模】

Subtask 1(10’):n,m≤10
Subtask 2(30’):n,m≤100
Subtask 3(10’):n=1,m≤1000
Subtask 4(20’):n=2,m≤1000
Subtask 5(30’):n,m≤1000

解析

现在左上方找到起点,再从起点向右方和下方延伸,

设最大延伸长度为x0,y0,显然x=x0和y=y0中必定有一个满足,设其中一个满足,再枚举另一个即可。

Code

#include<cstdio>
#include<algorithm>
using namespace std;
#define sum(x1,y1,x2,y2) (s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])
int n,m;
char c[][];
int s[][];
int ans=; int dfs(int x,int y,int wx,int wy)
{
if(sum(x,y+,x+wx-,y+wy)==wx*wy)return wx+dfs(x,y+,wx,wy);
if(sum(x+,y,x+wx,y+wy-)==wx*wy)return wy+dfs(x+,y,wx,wy);
return ;
} int main()
{
freopen("shine.in","r",stdin);
freopen("shine.out","w",stdout);
scanf("%d%d\n",&n,&m);
int flag=,px,py;
for(int i=;i<=n;i++)
gets(c[i]+);
for(int i=;i<=n+;i++)
for(int j=;j<=m+;j++)
{
if(c[i][j]=='X')
{
if(!flag){flag=;px=i;py=j;}
s[i][j]=s[i-][j]+s[i][j-]-s[i-][j-]+;
}
else s[i][j]=s[i-][j]+s[i][j-]-s[i-][j-];
}
int tmp,wx,wy;
for(tmp=px;c[tmp][py]=='X';tmp++);
wx=tmp-px;
for(int i=py;c[px][i]=='X';i++)
if(sum(px,py,px+wx-,i)==wx*(i-py+)&&dfs(px,py,wx,i-py+)+wx*(i-py+)==s[n][m])
ans=min(ans,wx*(i-py+));
for(tmp=py;c[px][tmp]=='X';tmp++);
wy=tmp-py;
for(int i=px;c[i][py]=='X';i++)
if(sum(px,py,i,py+wy-)==(i-px+)*wy&&dfs(px,py,i-px+,wy)+(i-px+)*wy==s[n][m])
ans=min(ans,(i-px+)*wy);
if(ans<=n*m) cout<<ans;
else printf("-1\n");
return ;
}

T3 小P的世界

题目

【题目描述】

小P的世界是一棵N(N<=1000)个节点的有根树(根为1),树上的每条边上都会有一个泡泡怪,小P从根节点开始移动(可以往回走),每经过一条边,小P都会打败边上的泡泡怪同时得到相应的泡泡气(每只泡泡怪只能被打败一次),已知 小P经过一条边需要花费 1 天时间,小P想知道自己晋级泡泡帝(泡泡气大于等于 K)至少需要的天数(如果 小P永远达不到泡泡帝,输出“QAQ”(不带引号))

【输入格式】

第一行两个用空格隔开的正整数 N,K。(1<=N<=1000,1<=K<=1000)
接下来 N - 1行每行三个用空格隔开的正整数 a,b,c,表示树上 a 与 b 之间连了一条边,打败边上的泡泡怪获得 c 点泡泡气(1<=a,b<=N,1<=c<=K/2,保证 a 是 b 的父亲)

【输出格式】

总共一行一个整数,表示答案

【数据规模】

保证树中每个节点至多两个孩子。
20 个测试点,每个测试点 5 分
1.TESTTEST 1~4: N,K <= 10
2.TSETTSET 5~20:N,K <= 1000 数据有梯度且大多随机,尽量优化自己的程序

解析

分别设置f[i][j]和g[i][j]. f[i][j]表示从i出发,不返回i得到j点泡泡气最少天数。

g[i][j]表示最终要返回i,其他和f数组一样,初始化f[i][0]=g[i][0]=0

转移时分两种情况,有一个孩子就直接赋值,两个孩子分两种情况走

Code

#include<iostream>
#include<cstdio>
#include<cstring> using namespace std; const int Size=+;
const int INF=1e8; int N,K;
int GO[Size][Size];
int RE[Size][Size];
int child[Size][];
int child_v[Size][];
int sum=; int read()
{
int num=,w=;
char ch=getchar();
while(ch<'' || ch>'')
{
if(ch=='-') w=-;
ch=getchar();
}
while(ch<='' && ch>='')
{
num=(num<<)+(num<<)+ch-'';
ch=getchar();
}
return num*w;
} inline void Init()
{
N=read();K=read();
for(int i=;i<N;i++)
{
int a=read(),b=read(),c=read();
child_v[a][child[a][] != ]=c;
child[a][child[a][] != ]=b;
sum+=c;
}
} int root = ; void DFS1(int k,int sum)
{
if(sum>=K)
{
child_v[k][]=child_v[k][]=;
return;
}
if(child[k][])
DFS1(child[k][],sum+child_v[k][]);
if(child[k][])
DFS1(child[k][],sum+child_v[k][]);
} void DFS(int k)
{
GO[k][]=RE[k][]=;
int lc=child[k][],rc=child[k][];
if(!lc) return;
DFS(lc);
if(rc) DFS(rc); int chongjg=child_v[k][];//走左节点能得到的泡泡气
for(int i=;i<=K-chongjg;i++)
{
if(GO[lc][i]>INF) break ;
if(GO[lc][i]+<GO[k][i+chongjg])
GO[k][i+chongjg]=GO[lc][i]+;
if(RE[lc][i]+<RE[k][i+chongjg])
RE[k][i+chongjg]=RE[lc][i]+;
}
//如果不存在右节点
if(rc==)
{
for(int i=K;i>=;i--)
//枚举每种情况
{
if(GO[k][i+]<GO[k][i])
GO[k][i]=GO[k][i+];
if(RE[k][i+]<RE[k][i])
RE[k][i]=RE[k][i+];
}
return ;
}
chongjg=child_v[k][];//走右节点能得到的泡泡气
for(int i=;i<=K-chongjg;i++)
{
if(GO[rc][i]>INF) break;
if(GO[rc][i]+ < GO[k][i+chongjg])
GO[k][i+chongjg]=GO[rc][i]+;
if(RE[rc][i]+ < RE[k][i+chongjg])
RE[k][i+chongjg]=RE[rc][i]+;
} chongjg=child_v[k][]+child_v[k][];//两个节点都走能得到的泡泡气
for(int i=;i<=K-child_v[k][];i++)
{
if(GO[lc][i]>INF) break;
for(int j=;j<=K-chongjg-i;j++)
{
if(GO[rc][j]>INF) break;
if(GO[lc][i]+RE[rc][j]+<GO[k][i+j+chongjg])
GO[k][i+j+chongjg]=GO[lc][i]+RE[rc][j]+;
if(RE[lc][i]+GO[rc][j]+<GO[k][i+j+chongjg])
GO[k][i+j+chongjg]=RE[lc][i]+GO[rc][j]+;
if(RE[lc][i]+RE[rc][j]+<RE[k][i+j+chongjg])
RE[k][i+j+chongjg]=RE[lc][i]+RE[rc][j]+;
}
}
for(int i=K;i>=;i--)
{
if(GO[k][i+]<GO[k][i])
GO[k][i]=GO[k][i+];
if(RE[k][i+]<RE[k][i])
RE[k][i]=RE[k][i+];
}
}
int main()
{
Init();
DFS1(root,);
if(sum<K){puts("QAQ");return ;};
memset(GO,,sizeof(GO));
memset(RE,,sizeof(RE));
DFS();
cout<<GO[][k];
return ;
}

泉五培训Day5的更多相关文章

  1. 泉五培训Day4

    T1 收果子 题目 [题目描述] 有一个果园,有n棵果树依次排成一排,其中已知第 i 棵果树上结了ai个果子.现在要按照果树编号顺序依次收果子,对于一个能装v个果树的果篮,收果子从第1棵果树开始,如果 ...

  2. 泉五培训Day3

    T1 家庭作业 题目 [问题描述] 小P为了能高效完成作业,规定每项作业花一个单位时间. 他的学习日从0时刻开始,有100000个单位时间.在任一时刻,他都可以选择编号1~N的N项作业中的任意一项作业 ...

  3. 泉五培训Day2

    T1 旅游 题目 [题目描述] 幻想乡有n个景点(从1开始标号),有m条双向的道路连在景点之间,每条道路有一个人气值d,表示这条道路的拥挤程度.小G不会经过那些人气值大于x的道路,她想知道有多少对景点 ...

  4. 泉五培训Day1

    T1 树学 题目 [问题描述] 给定一颗 n 个点的树,树边带权,试求一个排列 P,最大化下式 其中,calc(a, b)表示树上由a到b经过的最大边权. [输入格式] 第一行一个整数 n,表示点数下 ...

  5. 第五周 day5 python学习笔记

    1.软件开发的常规目录结构 更加详细信息参考博客:http://www.cnblogs.com/alex3714/articles/5765046.html         2.python中的模块 ...

  6. 长乐培训Day5

    T1 圆圈舞蹈 题目 [题目描述] 熊大妈的奶牛在时针的带领下,围成了一个圈跳舞.由于没有严格的教育,奶牛们之间的间隔不一致. 奶牛想知道两只最远的奶牛到底隔了多远.奶牛A到B的距离为A顺时针走和逆时 ...

  7. 常州培训 day5 解题报告

    第一题:(贪心) 题目大意:给出N*M的矩形,要用正方形将它铺满(正方形之间不能重叠),相邻的正方形颜色不能相同,颜色用ABCD表示.要求从上到下从左到右字典序最小. N,M<=100 解题过程 ...

  8. 纪中2018暑假培训day5提高b组改题记录

    因为今天省选组也做a组,以为今天a组会很难,就做了做b组.t1和t3强行暴力,好在有t2保底.t1和正解就差一点,然而考试时死活想不起来...... 今天改题可以少改一道了!ovo 救救孩子吧!t1T ...

  9. 8月清北学堂培训 Day5

    今天是杨思祺老师的讲授~ 最短路练习题: POJ 1125 Stockbroker Grapevine 有 N 个股票经济人可以互相传递消息,他们之间存在一些单向的通信路径.现在有一个消息要由某个人开 ...

随机推荐

  1. FlashFXP出现“数据Socket错误,连接超时”解决方案

    把FlashFXP选项中的"使用被动模式"的勾去掉就正常了. 或者在路由上映射服务端设定的被动模式所使用的所有端口,server-u就10个左右,微软的ftp是多少个,偶就不清楚了 ...

  2. 13、Selenium+python+API分类总结

    Selenium+python+API分类总结 http://selenium-python.readthedocs.org/index.html 分类 方法 方法描述 客户端操作 __init__( ...

  3. Matlab 2013a 和 VS2010 混合编程

    最近由于项目需求,某项目的算法是基于MATLAB完成的,在短时间内需要去调用算法功能.因此,基于MATLAB生成DLL, C 调用的方式完成. 环境:MATLAB 2013a + VS2010 + w ...

  4. 使用Aspose.Cell控件实现Excel高难度报表的生成

    1.使用Aspose.Cell控件实现Excel高难度报表的生成(一) http://www.cnblogs.com/wuhuacong/archive/2011/02/23/1962147.html ...

  5. 使用GreenDao 添加字段,删除表,新增表操作

    GreenDao 给我个人感觉 比一般的ORM框架要好很多,虽然说上手和其他的比起来,较复杂,但是如果使用熟练以后,你会爱上这个框架的 用这些ORM 框架给我的感觉都是,当升级时,都需要进行数据库所有 ...

  6. lunix重启service network restart错误Job for network.service failed. See 'system 或Failed to start LSB: Bring

    1.mac地址不对 通过ip addr查看mac地址,然后修改cd /etc/sysconfig/network-scripts/目录下的文件里面的mac地址 2.通过以下方法 systemctl s ...

  7. Struts2_Struts标签大致内容

    Struts-Tags1.通用标签 a) property b) set i.默认为 action scope,会将值放入 request 和 ActionContext中 ii. page.requ ...

  8. Oracle 数据库自动备份方案

    1.新建 backup.bat脚本 @echo off echo ================================================ echo Windows环境下Ora ...

  9. python+pywinauto之PC端自动化一

    所需软件安装: 1.下载 pywinauto 安装参考: https://jingyan.baidu.com/article/414eccf6a1a3906b421f0a59.html 下载地址: h ...

  10. git 因线上分支名重复导致无法拉取代码

    有时 git pull 或 git fetch 时发现 git 报了个异常,说法像是无法将线上某个分支与本地分支合并,由于分支是...(很长的hash)但是分支却是...(很长的hash) 仔细查查后 ...