Monthly Expense + Copying Books + Aggressive cows

来源:互联网 发布:java用户登录权限 编辑:程序博客网 时间:2024/05/21 07:49

这几个题都是典型的二分题目,都出现什么最大的最小 最小的最大什么的,

这种绝壁二分,思想都是一样的,发到一起吧,对于这类题目,都是在确定上下限之后,

判断当前的值是否满足题目中要求,比如说距离大小,分组多少等等具体问题具体分析   详见题目

Monthly Expense

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 120   Accepted Submission(s) : 38
Problem Description

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: <i>N</i> and <i>M</i> <br>Lines 2..<i>N</i>+1: Line <i>i</i>+1 contains the number of dollars Farmer John spends on the <i>i</i>th day
 

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

Sample Input
7 5100400300100500101400
 

Sample Output
500

题意:农夫打好算盘,n个月,分m组,每组必须是连续的,每个月可以话ai的钱,在每组和尽可能小的情况下,输出每组中最大值

思路:当前mid如果可以将其分为>m组 则说明当前mid的值偏小  注意下low high与mid变幻时的关系就行了

  • Source Code
    #include<iostream>#include<stdio.h>#include<iomanip>#include<string.h>using namespace std;int main(){    int n,m;    int i,j;    int val[100001];    while(cin>>n>>m)    {        int max=0;        int  sum=0;        memset(val,0,sizeof(val));        for(i=0;i<n;i++)        {            cin>>val[i];            sum+=val[i];            if(val[i]>max)            max=val[i];            }        if(m==1)cout<<sum<<endl;        else {        int mid,low=max,high=sum;        while(high>low)        {            mid=(low+high)/2;            int temp=1;            sum=0;            for(i=0;i<n;i++)            {                sum+=val[i];                if(sum>mid)                {                    sum=val[i];                    temp++;                    }                }            if(temp>m)            low=mid+1;            else high=mid-1;                }        cout<<low<<endl;        }    }    return 0;    }

Copying Books

Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other)
Total Submission(s) : 100   Accepted Submission(s) : 35
Problem Description
Before the invention of book-printing, it was very hard to make a copy of a book. All the contents had to be re-written by hand by so called scribers. The scriber had been given a book and after several months he finished its copy. One of the most famous scribers lived in the 15th century and his name was Xaverius Endricus Remius Ontius Xendrianus (Xerox). Anyway, the work was very annoying and boring. And the only way to speed it up was to hire more scribers. 

Once upon a time, there was a theater ensemble that wanted to play famous Antique Tragedies. The scripts of these plays were divided into many books and actors needed more copies of them, of course. So they hired many scribers to make copies of these books. Imagine you have m books (numbered 1, 2 ... m) that may have different number of pages (p1, p2 ... pm) and you want to make one copy of each of them. Your task is to divide these books among k scribes, k <= m. Each book can be assigned to a single scriber only, and every scriber must get a continuous sequence of books. That means, there exists an increasing succession of numbers 0 = b0 < b1 < b2, ... < bk-1 <= bk = m such that i-th scriber gets a sequence of books with numbers between bi-1+1 and bi. The time needed to make a copy of all the books is determined by the scriber who was assigned the most work. Therefore, our goal is to minimize the maximum number of pages assigned to a single scriber. Your task is to find the optimal assignment. 
 

Input
The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case consists of exactly two lines. At the first line, there are two integers m and k, 1 <= k <= m <= 500. At the second line, there are integers p1, p2, ... pm separated by spaces. All these values are positive and less than 10000000.
 

Output
For each case, print exactly one line. The line must contain the input succession p1, p2, ... pm divided into exactly k parts such that the maximum sum of a single part should be as small as possible. Use the slash character ('/') to separate the parts. There must be exactly one space character between any two successive numbers and between the number and the slash. <br> <br>If there is more than one solution, print the one that minimizes the work assigned to the first scriber, then to the second scriber etc. But each scriber must be assigned at least one book.
 

Sample Input
29 3100 200 300 400 500 600 700 800 9005 4100 100 100 100 100
 

Sample Output
100 200 300 400 500 / 600 700 / 800 900100 / 100 / 100 / 100 100
题意:与上一题神似   只不过改成了输出分组的情况

思路:虽然很相似,但是一直调不通,到网上找了找药方,在判断当前值是否符合的时候,从n到1倒过来,

cnt是从0开始的,所以==m-1,记下当前的数据vis,(是否需要划线),找到方案便先记录下vis 的位置

否则vis的值变化就wa了

  • Source Code
    #include<iostream>#include<stdio.h>#include<string.h>using namespace std;int n,m;long long val[1001];int vis[1001];int a[1001];bool judge(long long mid){    long long sum=0;    int cnt=0;    memset(vis,0,sizeof(vis));    for(int i=n;i>=1;i--)    {        if(sum+val[i]<=mid&&i>=m-cnt)            sum+=val[i];        else        {            cnt++;            sum=val[i];            vis[i]= 1;        }    }    if(cnt==m-1)    {        for(int i=0;i<=n;i++)        a[i]=vis[i];        return true;        }    return false;    }int main(){    int i,j;    int t;    cin>>t;    while(t--)    {        cin>>n>>m;        long long sum=0;        long long max=0;        memset(vis,0,sizeof(vis));        memset(a,0,sizeof(a));        for(i=1;i<=n;i++)        {            cin>>val[i];            sum+=val[i];            if(max<val[i])            max=val[i];            }        long long mid,low=max,high=sum;        while(low<=high)        {            mid=(low+high)/2;            if(judge(mid))            {                high=mid-1;                }            else low=mid+1;            }        //cout<<low<<endl;        for(i=1;i<n;i++)        {            cout<<val[i]<<" ";            if(a[i]==1)            cout<<"/ ";            }        cout<<val[n]<<endl;        }    return 0;    }

Aggressive cows

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 100   Accepted Submission(s) : 34
Problem Description
Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000). 

His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?
 

Input
* Line 1: Two space-separated integers: N and C <br> <br>* Lines 2..N+1: Line i+1 contains an integer stall location, xi
 

Output
* Line 1: One integer: the largest minimum distance
 

Sample Input
5 312849

Sample Output
3
题意:n间牛舍,m头牛,如果牛离得太近便会打架,所以就是求尽可能的让他们之间的距离大的最小值

思路:。。。。。。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
    int i,j,k;
    int n,c;
    int map[100001];
    int num,temp;
    while(scanf("%d %d",&n,&c)!=EOF)
    {
        memset(map,0,sizeof(map));
        int max=0;
        for(i=0;i<n;i++)
        {
            scanf("%d",&map[i]);
        }
        sort(map,map+n);
        int mid,low=0,high=map[n-1]-map[0];
        while(high>=low)
        {
            mid=(low+high)/2;
            temp=map[0];
            num=0;
            for(i=1;i<n;i++)
            {
                if(map[i]-temp>=mid)
                {
                    num++;
                    temp=map[i];
                    }
                }
            if(num>=c-1)
            low=mid+1;
            else high=mid-1;
            }
        cout<<low-1<<endl;
        }
    return 0;
    }


原创粉丝点击