2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)

G. Car Repair Shop

题目链接:http://codeforces.com/contest/730/problem/G

题意:

  修车店提前问好n位顾客想要送车的时间Si和修车辆车的时间Ki,然后修车店安排时间,对于第i辆车如果【Si,Si+Ki-1】这段时间是有空的修车,如果没空则找到第一天满足【Ti,Ti+Ki-1】这段时间有空,安排修车,注意Ti可以<Si。输出每辆车修车的时间。

input
3
9 2
7 3
2 4
output
9 10
1 3
4 7
input
4
1000000000 1000000
1000000000 1000000
100000000 1000000
1000000000 1000000
output
1000000000 1000999999
1 1000000
100000000 100999999
1000001 2000000

分析:
  在比赛想复杂了,结果错了。正确的思维使用数组l和数组r维护1-n辆车对用的修车时间。输入的起始时间为x,持续时间为y。l[0]和r[0]都置为0.l[0]和r[0]用在当前时间如果已经安排了修车的话,从l[0]+1时刻开始找合适的时间安排
  对于来修的车,如果他与之前的没有冲突,直接用这段时间修车,即l[i]=x,r[i]=x+y-1。如果有冲突,让l[i]=r[j]+1,r[i]=l[i]+y-1;判断这段时间与之前的时候有冲突,没冲突就选这段时间。j从0-i循环。
代码:
  
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1111;
int l[MAXN], r[MAXN], n, cnt;
//用于检验当前时间是否与之前安排好的时间冲突,没冲突返回true
inline bool check(int x, int y) {
    for (int i = 1; i <= cnt; ++i)
        if (!(x > r[i] || y < l[i])) return false;
    return true;
}

int main() {
    scanf("%d", &n);
    cnt = 0;
    for (int i = 1; i <= n; ++i) {
        int x, y;
        cin >> x >> y;
        if (check(x, x + y - 1)) {
            l[++cnt] = x; r[cnt] = x + y - 1;
        } else {
            for (int j = 0; j <= cnt; ++j) {
                if (check(r[j] + 1, r[j] + y)) {
                    l[++cnt] = r[j] + 1; r[cnt] = r[j] + y;
                    break;
                }
            }
        }
        cout << l[i] << " " << r[i] << endl;
        //用于维持l数组从小到大。
        for (int j = 1; j < cnt; ++j)
            for (int k = j + 1; k <= cnt; ++k)
                if (l[j] > l[k]) swap(l[j], l[k]), swap(r[j], r[k]);
    }
}

B题:Minimum and Maximum

  题目链接:http://codeforces.com/contest/730/problem/B

  题意:

    其实就是个模拟人机询问,给定一个数组A,你不知道其内容,然后你输出“? x y”代表向电脑询问A[x]和A[y]的关系,电脑输入>,<,=表示其关系,但要求输入的询问个数不能超过[3*n/2]-2个。最后用“! min max”代表输出结果,输出数组中第几个数是最小值,第几个数是最大值。

  分析:

    做法就是模拟归并,对于每个数组询问i*2和i*2+1的关系,将大的值放入一个集合,小的放入另一个,这样询问n/2次。如果n为奇数的话,把最后一个放入这两个集合。然后分别对每个集合询问,这个直接就询问一遍问出对应的最大值或最小值就好了。结果我们错在输出的内容没有没有从缓冲区调出,也是醉了。

 

#include <bits/stdc++.h>

std::vector<int> up, down;

int query(int i, int j) {
    if (i == j) return 0;
    printf("? %d %d\n", i + 1, j + 1);
    fflush(stdout);//这句话必须加,作用是立刻将printf的内容输出,不加这句话printf会先将输出内容存放到缓冲区,然后等时间片轮转到输出程序时在输出
    char ans[3]; scanf("%s", ans);
    if (ans[0] == '<') return -1;
    else if (ans[0] == '=') return 0;
    else return 1;
}

int main() {
    int T; scanf("%d", &T);
    for (; T --; ) {
        int n; scanf("%d", &n);
        up.clear(); down.clear();
        for (int i = 0; i < n / 2; ++ i) {
            if (query(i * 2, i * 2 + 1) < 0) {
                up.push_back(i * 2 + 1);
                down.push_back(i * 2);
            }
            else {
                down.push_back(i * 2 + 1);
                up.push_back(i * 2);
            }
        }
        if (n % 2 != 0) {
            up.push_back(n - 1);
            down.push_back(n - 1);
        }
        int maxindex = up[0], minindex = down[0];
        for (int i = 1; i < (int)up.size(); ++ i) {
            if (query(up[i], maxindex) > 0)
                maxindex = up[i];
        }
        for (int i = 1; i < (int)down.size(); ++ i) {
            if (query(down[i], minindex) < 0)
                minindex = down[i];
        }
        printf("! %d %d\n", minindex + 1, maxindex + 1);
        fflush(stdout);
    }
}

J题:Bottles

  题目链接:http://codeforces.com/contest/730/problem/J

  题意:

    给出每个瓶子现在装得水的体积,然后给出每个瓶子的体积,然后瓶子之间可以互相倒水,每倒出一体积水花费为1,然后问最少用几个瓶子装这些水,然后最少花费是多少。

  分析:最少用几个桶很简单能求出来。然后背包出这些桶花费最少,比赛时简直智障,一直想贪心,都没往背包上想。

  

#include <bits/stdc++.h>
using namespace std;
struct qwe
{
    int a,b;
} e[110];
int cmp(qwe x,qwe y)
{
    return (x.b>y.b || (x.b==y.b && x.a>y.a));//体积大的排序,如果体积相同就按照已经有水多的的在前面
}
int cmp1(qwe x,qwe y)//按照体积小的排序
{
    return (x.b<y.b);
}
int dp[110][10010],s[110];
int main()
{
    //freopen("C:\\Users\\acer\\Desktop\\in.txt","r",stdin);
    int n;
    scanf("%d",&n);
    int sum=0;//总共有多少水
    for(int i=1;i<=n;i++) 
        scanf("%d",&e[i].a),sum+=e[i].a;
    for(int i=1;i<=n;i++) 
        scanf("%d",&e[i].b);
    sort(e+1,e+1+n,cmp);
    int t=0,q=0;
    int ans;
    for(int i=1;i<=n;i++)
    {
        t+=e[i].b;
        if(t>=sum)
        {
            ans=i;
            break;
        }
    }//找出最少的桶数
    sort(e+1,e+1+n,cmp1);
    for(int i=1;i<=n;i++) 
        s[i]=s[i-1]+e[i].b;
    memset(dp,0xBf,sizeof(dp));
    dp[0][0]=0;//dp[j][k]表示j个桶,最多装多少水
    for(int i=1;i<=n;i++)//用多少桶
    {
        for(int j=min(i,ans);j>0;j--)
            for (int k=s[i];k>=e[i].b;k--)
            {
                    dp[j][k]=max(dp[j][k],dp[j-1][k-e[i].b]+e[i].a);
            }
    }
    int fin=0;
    for (int k=s[n];k>=sum;k--)
        fin=max(fin,dp[ans][k]);
    printf("%d %d\n",ans,sum-fin);
    return 0;
}

 

posted @ 2016-10-24 19:23  幻世沉溺  阅读(671)  评论(0编辑  收藏  举报