您的位置:首页 > 其它

sduacm16级寒假训练 贪心二分

2017-01-25 13:47 459 查看


 A

 HDU
- 2037   

“今年暑假不AC?” 

“是的。” 

“那你干什么呢?” 

“看世界杯呀,笨蛋!” 

“@#$%^&*%...” 

确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。 

作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目) 

Input输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。 

Output对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
Sample Input
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0


Sample Output
5


package A;
/*
* 题目大意:给出节目数,开始和结束时间 求最多能看的节目数
* 解题思路:贪心 按照结束时间排序  节目结束时间越早看的越多
*
* 其实可以构建一个类去直接sort,当时忘记了,手写了一个排序。
*/
import java.util.*;
public class Main {
public static void main(String []args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
if(n==0){
return;
}
int start[] = new int
,end[] = new int
;
for(int i=0;i<n;i++){
start[i] = sc.nextInt(); end[i] = sc.nextInt();
}
for(int i = 0;i<n;i++){
for(int j = i+1;j<n;j++){
if(end[j]<end[i]){
int temp1 = start[i]; start[i] = start[j]; start[j] = temp1;
int temp2 = end[i]; end[i] = end[j] ; end[
4000
j] = temp2;
}
}
}
int count=0,mark=0;
for(int i = 0;i<n;i++){
if(start[i]>=mark){  //看完一个就标记一次结束时间 看能看的
count++;
mark = end[i];
}
}
System.out.println(count);

}
}
}



B

HDU - 1051   

There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine to
prepare processing a stick. The setup times are associated with cleaning operations and changing tools and shapes in the machine. The setup times of the woodworking machine are given as follows: 

(a) The setup time for the first wooden stick is 1 minute. 

(b) Right after processing a stick of length l and weight w , the machine will need no setup time for a stick of length l' and weight w' if l<=l' and w<=w'. Otherwise, it will need 1 minute for setup. 

You are to find the minimum setup time to process a given pile of n wooden sticks. For example, if you have five sticks whose pairs of length and weight are (4,9), (5,2), (2,1), (3,5), and (1,4), then the minimum setup time should be 2 minutes since there is
a sequence of pairs (1,4), (3,5), (4,9), (2,1), (5,2). 

InputThe input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case consists of two lines: The first line has an integer n , 1<=n<=5000, that represents the number of wooden sticks in the
test case, and the second line contains n 2 positive integers l1, w1, l2, w2, ..., ln, wn, each of magnitude at most 10000 , where li and wi are the length and weight of the i th wooden stick, respectively. The 2n integers are delimited by one or more spaces. 

OutputThe output should contain the minimum setup time in minutes, one per line. 

Sample Input
3
5
4 9 5 2 2 1 3 5 1 4
3
2 2 1 1 2 2
3
1 3 2 2 3 1


Sample Output
2
1
3


package B;
/*
* 题目大意:给出n个木头的length和weight,一开始需要一分钟启动时间,如果加工更长更重(或相等)不需要时间,否则需要一分钟调整。求最少时间
* 解题思路:贪心 双关键字排序   按照l和w递增顺序遍历即可
*/
import java.util.*;

class Sticks implements Comparable<Sticks>{
int len,wid;
public Sticks(int len,int wid){
this.len = len;
this.wid = wid;
}
@Override
public int compareTo(Sticks o) {
if(this.len==o.len)		return this.wid-o.wid;
else	 return this.len-o.len;
}
}

public class Main {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int T = sc.nextInt();
for(int a = 0;a<T;a++){
int n = sc.nextInt();
Sticks[] woods = new Sticks
;
for(int i = 0;i<n;i++){
woods[i] = new Sticks(sc.nextInt(),sc.nextInt());
}
Arrays.sort(woods);   //第一关键字是length
int mark = 0,count = 0;
boolean flag = false;
for(int i = 0;i<n;i++){

for(int j = 0;j<n;j++)
if(woods[j].len>0) {   //选出最短的且未被选过的木头
mark = j;
break;
}

for(int k = 0;k<n;k++){
if(woods[k].len>0&&mark!=k&&woods[k].wid>=woods[mark].wid){   //依次比较,所有不需要setup的都扔出去
woods[mark].len = -1;
mark = k;    //更新为当前处理木头
}
}
for(int j = 0;j<n;j++){
if(woods[j].len>0){    //检查剩余木头(剩下的均需要setup)
flag = true;
break;
}
else flag = false;
}
woods[mark].len=-1; // 当前的最后一根扔出去 开始新一轮处理
if(flag) count++;  //setup
}
System.out.println(count);
}
}

}

}



C

 HDU
- 2141   

Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X. 

InputThere are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences
B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers. 

OutputFor each case, firstly you have to print the case number as the form "Case d:", then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print "YES", otherwise print "NO". 

Sample Input
3 3 3
1 2 3
1 2 3
1 2 3
3
1
4
10


Sample Output
Case 1:
NO
YES
NO


package C;
/*
* 题目大意:给三个序列ABC,给一个序列X,能否实现Ai+Bj+Ck=X
* 解题思路:搜索即可,但是直接暴搜会T,优化最内层二分查找X也会T,因此二分查找A+B=X-C
*/
import java.util.*;
public class Main {
static int d = 1;

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int L = sc.nextInt(),M = sc.nextInt(),N=sc.nextInt();
int [] arr1 = new int[L],arr2 = new int[M],arr3 = new int
;
for(int i = 0;i<L;i++)  arr1[i] = sc.nextInt();
for(int i = 0;i<M;i++)  arr2[i] = sc.nextInt();
for(int i = 0;i<N;i++)  arr3[i] = sc.nextInt();
int S = sc.nextInt();

int []sum = new int[L*M];
int k = 0;
for(int i = 0;i<L;i++){
for(int j = 0;j<M;j++)                     //算出所有A+B存入sum
sum[k++] = arr1[i]+arr2[j];
}
Arrays.sort(sum);
System.out.println("Case "+d+":");
for(int i = 0;i<S;i++){
int X = sc.nextInt();
for(int j = 0;j<N;j++){              //二分查找x-c[j]
binS(0, k-1, X-arr3[j], sum);
if(flag){
System.out.println("YES");
break;
}
}
if(!flag) System.out.println("NO");
}
d++;
}

}

static boolean flag = false;
static void binS(int left,int right,int tar,int sum[]){  //二分套路要记住(敲黑板)
while(left<=right){           //二分搜索l<=f  然而二分答案的时候l<r...
int mid = (left+right)/2;
if(sum[mid]>tar){
right = mid-1;
}
if(sum[mid]<tar){
left = mid+1;
}
if(sum[mid]==tar){
flag = true;
return;
}
}
flag = false;
}
}


D

 HDU
- 4004   

The annual Games in frogs' kingdom started again. The most famous game is the Ironfrog Triathlon. One test in the Ironfrog Triathlon is jumping. This project requires the frog athletes to jump over the river. The width of the river
is L (1<= L <= 1000000000). There are n (0<= n <= 500000) stones lined up in a straight line from one side to the other side of the river. The frogs can only jump through the river, but they can land on the stones. If they fall into the river, they 

are out. The frogs was asked to jump at most m (1<= m <= n+1) times. Now the frogs want to know if they want to jump across the river, at least what ability should they have. (That is the frog's longest jump distance).

InputThe input contains several cases. The first line of each case contains three positive integer L, n, and m. 

Then n lines follow. Each stands for the distance from the starting banks to the nth stone, two stone appear in one place is impossible.
OutputFor each case, output a integer standing for the frog's ability at least they should have.
Sample Input
6 1 2
2
25 3 3
11
2
18


Sample Output
4
11


package D;
/*
* 题目大意:一条河宽L,有n个石头,给出每个石头到河岸的距离,青蛙可以跳m次,青蛙最小需要跳多远的能力,才能到对岸
* 解题思路:最大值最小,二分。然而java还是T,最后挂了快速io竟然a了(迷茫)
*/
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.*;
public class Main {

//读入整形
static int nextInt() throws IOException{
in.nextToken();
return (int)in.nval;
}
//快速输入
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
//快速输出
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
//常规输出
static Scanner sc = new Scanner(new BufferedInputStream(System.in));

public static void main(String[] args) throws IOException {

while(in.nextToken()!=StreamTokenizer.TT_EOF){
int L=(int)in.nval;
int n = nextInt();
int m = nextInt();
//			int m = nextInt();
int []dists = new int[n+1];
for(int i = 0;i<n;i++) dists[i] = nextInt();
dists
= L;    //把河岸当作了最后一块石头

Arrays.sort(dists);

int left = 0 , right = L;
while(left<right){    //二分
int mid = (left+right)/2;
int jump = mid;
//--------------------------------------------------------------------------------------
int pos = 0,stone = 0,s=0;  //判断能否到对岸
boolean flag = false;
for(int i = 0;i<m;i++){
while(stone<dists.length&&dists[stone]<=s+jump){  //跳能力所及最远的石头
pos = dists[stone];                          //直接找最远不好找,因此一个一个石头判断直到不能再跳算作跳了一次最远。
stone++;
}
s=pos;//更新位置
}
if(s>=L)  flag = true;
else flag = false;
//---------------------------------------------------------------------------------------

if(flag) right=mid;
else left = mid+1;
}
out.println(left);
out.flush();
}
}

}



E

POJ
- 3617  

FJ is about to take his N (1 ≤ N ≤ 2,000) cows to the annual"Farmer of the Year" competition. In this contest every farmer arranges his cows in a line and herds them past the judges.

The contest organizers adopted a new registration scheme this year: simply register the initial letter of every cow in the order they will appear (i.e., If FJ takes Bessie, Sylvia, and Dora in that order he just registers BSD). After the registration phase
ends, every group is judged in increasing lexicographic order according to the string of the initials of the cows' names.

FJ is very busy this year and has to hurry back to his farm, so he wants to be judged as early as possible. He decides to rearrange his cows, who have already lined up, before registering them.

FJ marks a location for a new line of the competing cows. He then proceeds to marshal the cows from the old line to the new one by repeatedly sending either the first or last cow in the (remainder of the) original line to the end of the new line. When he's
finished, FJ takes his cows for registration in this new order.

Given the initial order of his cows, determine the least lexicographic string of initials he can make this way.

Input

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains a single initial ('A'..'Z') of the cow in the ith position in the original line

Output

The least lexicographic string he can make. Every line (except perhaps the last one) contains the initials of 80 cows ('A'..'Z') in the new line.

Sample Input
6
A
C
D
B
C
B


Sample Output
ABCBCD


package E;
/*
* 题目大意:
aede
FJ参赛前要给他的牛排序,让牛站成一排,然后只能不断的从队头或队尾取牛,放到另一列队尾,使得新列尽可能按照字典序排列。
* 解题思路:以此比较取出字典序靠前的,一样就比较下一个,如果全部一样,就随便取。
* 一开始把前后一样比较下一个写复杂了,实际上一个while加两个判断就能解决,不需要开第三个if,反而更麻烦
*/

import java.util.*;

public class Main {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int count = 0;
String str = sc.nextLine();
int N = Integer.parseInt(str);
char[] cows = new char
;
for (int i = 0; i < N; i++)
cows[i] = sc.nextLine().charAt(0);

int start = 0;
int end = N-1;
boolean flag = false;  //通过flag来决定输出,而不是判断后直接输出
while (start <= end) {
for (int i = 0; i+start <= end; i++) {
if (cows[start+i] < cows[end-i]) {
flag = true;
break;
}
if (cows[start+i] > cows[end-i]) {
flag = false;
break;
}
}                              //如果最终全部一样,跳出for,随便输出一个即可。
if(flag){
System.out.print(cows[start]);
start++;
}
else{
System.out.print(cows[end]);
end--;
}
count++;
if (count == 80) {       //80个要换行啊换行啊换行
System.out.println();
count = 0;
}
}
}
}
}



F

 POJ
- 3273

Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤ moneyi ≤ 10,000) that he will need to spend each day over
the next N (1 ≤ N ≤ 100,000) days.

FJ wants to create a budget for a sequential set of exactly M (1 ≤ M ≤ N) fiscal periods called "fajomonths". Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.

FJ's goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.

Input
Line 1: Two space-separated integers: N and M 

Lines 2.. N+1: Line i+1 contains the number of dollars Farmer John spends on the ith day

Output
Line 1: The smallest possible monthly limit Farmer John can afford to live with.

Sample Input
7 5
100
400
300
100
500
101
400


Sample Output
500


Hint
If Farmer John schedules the months so that the first two days are a month, the third and fourth are a month, and the last three are their own months, he spends at most $500 in any month. Any other method of scheduling gives a
larger minimum monthly limit.

package F;
/*
* 题目大意:Farmer John的钱快花光了,接下来N天规划成M个fajomonths,使得消费最高的fajomonths花钱最小。
* 解题思路:最大值最小,二分答案。
*/
import java.util.*;
public class Main {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int N = sc.nextInt(),M = sc.nextInt();
int [] costs = new int
;
int total = 0,max = 0;
for(int i = 0;i<N;i++){
costs[i] = sc.nextInt();
total += costs[i];                  //记录N天总花费
if(max<costs[i]) max =costs[i];   //记录花费max的一天
}

int left = 0,right = total;
while(left<right){   //对答案进行二分
int mid = (left+right)/2;
int sum = 0,count = 1;
for(int i = 0;i<N;i++){
if(sum+costs[i]<=mid)
sum+= costs[i];       //只要没超就合并成一个fajomonths
else{
count++;         //无法合并
sum = costs[i];
}
}
if(count>M) left = mid+1;   //months太多说明答案太小
else right = mid;       //答案太大
}
if(right>=max)
System.out.println(right);    //答案可能大于max,第一次因为少这个判断wa了
else
System.out.println(max);
}

}

}



G

POJ
- 3111 

Demy has n jewels. Each of her jewels has some value vi and weight wi.

Since her husband John got broke after recent financial crises, Demy has decided to sell some jewels. She has decided that she would keep k best jewels for herself. She decided to keep such jewels that their specific value is as large as possible.
That is, denote the specific value of some set of jewels S = {i1, i2, …, ik} as


.
Demy would like to select such k jewels that their specific value is maximal possible. Help her to do so.

Input

The first line of the input file contains n — the number of jewels Demy got, and k— the number of jewels she would like to keep (1 ≤ k ≤ n ≤ 100 000).

The following n lines contain two integer numbers each — vi and wi (0 ≤ vi ≤ 106, 1 ≤ wi ≤ 106, both the sum of all vi and
the sum of all wi do not exceed 107).

Output

Output k numbers — the numbers of jewels Demy must keep. If there are several solutions, output any one.

Sample Input
3 2
1 1
1 2
1 3


Sample Output
1 2


package G;
/*
* 题目大意:Demy有n个珠宝,每一个都有价值v和重量w,分手后没钱要卖珠宝,自己留下k个,使留下的的珠宝满足S=∑vi/∑wi  (i=1...k)最大
* 解题思路:01分数规划
* 根据题意,选出k个物品,使得sum(vi) / sum(wi)最大,即sum(vi) / sum(wi) >= x,求出x的最大值,即最小值最大问题,因此可以二分枚举x,然后这样check:
* 变形得f=sum(vi) - x * sum(wi) >= 0,即f=sum(vi - x * wi) >= 0,则只需用贪心法将vi - x * wi排序,选出前k大来,加和 >= 0即可
*/
import java.util.*;

class jewel implements Comparable<jewel> {    //记录珠宝的id和f
double f;
int id;

@Override
public int compareTo(jewel o) {
// TODO Auto-generated method stub
if(o.f>this.f)
return 1;
else
return -1;
}
}

public class Main {
static int n, k;
static jewel[] js;
static int[] v, w;

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
n = sc.nextInt();
k = sc.nextInt();
v = new int
;
w = new int
;
js = new jewel
;
for (int i = 0; i < n; i++)
js[i] = new jewel();

for (int i = 0; i < n; i++) {
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
double left = 0, right = 1e7 + 1;
for (int i = 0; i < 50; i++)  //二分答案     30次精度不够 100次T
{
double mid = (left + right) / 2;
if (dis(mid))
left = mid;
else
right = mid;
}
for (int i = 0; i < k - 1; i++)
System.out.print(js[i].id + " ");
System.out.println(js[k - 1].id);
}
}

static boolean dis(double x) {
for (int i = 0; i < n; i++) {      //求x的临界值使得sum(vi-x*wi)=0
js[i].f = v[i] - w[i] * x;
js[i].id = i + 1;
}
Arrays.sort(js);     //排序取前k大
double sum = 0;
for (int i = 0; i < k; i++)
sum += js[i].f;
return sum >= 0;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: