CCF练习

201709-2 公共钥匙盒

问题描述

  有一个学校的老师共用N个教室,按照规定,所有的钥匙都必须放在公共钥匙盒里,老师不能带钥匙回家。每次老师上课前,都从公共钥匙盒里找到自己上课的教室的钥匙去开门,上完课后,再将钥匙放回到钥匙盒中。
  钥匙盒一共有N个挂钩,从左到右排成一排,用来挂N个教室的钥匙。一串钥匙没有固定的悬挂位置,但钥匙上有标识,所以老师们不会弄混钥匙。
  每次取钥匙的时候,老师们都会找到自己所需要的钥匙将其取走,而不会移动其他钥匙。每次还钥匙的时候,还钥匙的老师会找到最左边的空的挂钩,将钥匙挂在这个挂钩上。如果有多位老师还钥匙,则他们按钥匙编号从小到大的顺序还。如果同一时刻既有老师还钥匙又有老师取钥匙,则老师们会先将钥匙全还回去再取出。
  今天开始的时候钥匙是按编号从小到大的顺序放在钥匙盒里的。有K位老师要上课,给出每位老师所需要的钥匙、开始上课的时间和上课的时长,假设下课时间就是还钥匙时间,请问最终钥匙盒里面钥匙的顺序是怎样的?

输入格式

  输入的第一行包含两个整数N, K
  接下来K行,每行三个整数w, s, c,分别表示一位老师要使用的钥匙编号、开始上课的时间和上课的时长。可能有多位老师使用同一把钥匙,但是老师使用钥匙的时间不会重叠。
  保证输入数据满足输入格式,你不用检查数据合法性。

输出格式

  输出一行,包含N个整数,相邻整数间用一个空格分隔,依次表示每个挂钩上挂的钥匙编号。

样例输入

5 2
4 3 3
2 2 7

样例输出

1 4 3 2 5

这个题需要根据不同的时间点 拿走钥匙 归还钥匙,每个操作有一个时间点,直接记录这个时间点要借还是还几号钥匙即可,数据量较小2000。都存放在vector中,直接对钥匙数组进行操作即可。分析问题要找到关键的影响因素。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node
{
    int w,c;
    int ok;
    node(int w,int c,int ok):w(w),c(c),ok(ok){}
    //注意学会用结构体中的析构函数 括冒分括弧
};
vector<node> v;
bool cmp(node a,node b)
{
    if(a.c!=b.c) return a.c<b.c;
    else if(a.ok!=b.ok) return a.ok>b.ok;
    else return a.w<b.w;
}
int main()
{
    int n,k,x;
    scanf("%d%d",&n,&k);
    int w,s,c;
    for(int i=0;i<k;i++){
        scanf("%d%d%d",&w,&s,&c);
        v.push_back(node(w,s,0));//直接填写 node()
        v.push_back(node(w,s+c,1));
    }
    sort(v.begin(),v.end(),cmp);
    int a[n+5];
    for(int i=1;i<=n;i++)
        a[i]=i;
    for(int i=0;i<v.size();i++){
        if(v[i].ok==0){
            for(int j=1;j<=n;j++){
               if(a[j]==v[i].w){
                   a[j]=0;break;
               }
            }
        }
        else{
            for(int j=1;j<=n;j++){
                if(a[j]==0){
                    a[j]=v[i].w;break;
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(i==1) printf("%d",a[i]);
        else printf(" %d",a[i]);
    }
    printf("\n");
    return 0;
}

201809-4再卖菜

2*a1<=(x1+x2)<=2*a1+1

3*a2<=(x1+x2+x3)<=3*a2+2

2*an<=(x(n-1)+xn)<=2*an+1

但是呢?差分约束不是都两个么 ,这个属于三个,那么考虑s=x0+x1+x2+....xn,之后就又有了一组式子,这个x0必然为0

2*a1<=s2-s0<=2*a1+1

3*a2<=s3-s0<=3*a2+2

3*a3<=s4-s1<=3*a3+2

2*an<=sn-s(n-2)<=2*an+1

之后就是差分约束不是方向统一么,那么就统一用>=吧,之后式子拆解成两个

s2-s0>=2*a1  s0-s2>=-2*a1-1

s3-s0>=3*a3  s0-s3>=-3*a2-2

sn-s(n-2)>=2*an  s(n-2)-sn>=-2*an-1

也就是sj-si>=x,建立从i到j有一条x的边,之后记住差分约束就是<=求解最短路,>=求解最长路,然后这个题拿spfa跑最长路,最后还有一点要注意的就是各个x都要是正整数,也就是还得需要建立一个约束条件,si-s(i-1)=xi,因为xi>=1,所以si-s(i-1)>=1

 
#include<bits/stdc++.h>
 
using namespace std;
 
const int maxm=1e3+50;
const int maxn=5e2+50;
 
struct edge{
    int v,w,next;
};
edge edges[maxm];
int head[maxn],tot;
 
void add_edges(int u,int v,int w)
{
    edges[tot].v=v;
    edges[tot].w=w;
    edges[tot].next=head[u];
    head[u]=tot++;
}
 
int n;
bool vis[maxn];
int cnt[maxn];
int dist[maxn];
 
bool spfa()
{
    queue<int>q;
    for(int i=0;i<n;i++){
        q.push(i);
        vis[i]=false;dist[i]=0;cnt[i]=1;
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=edges[i].next){
            int v=edges[i].v;
            if(dist[v]<dist[u]+edges[i].w){
                dist[v]=dist[u]+edges[i].w;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                    if(++cnt[v]>n){
                        return false;
                    }
                }
            }
        }
    }
    return true;
}
 
int a[maxn];
 
int main()
{
    memset(head,-1,sizeof(head));
    tot=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=0;i<n-2;i++){
        add_edges(i+3,i,-(a[i+2]*3+2));
        add_edges(i,i+3,a[i+2]*3);
    }
    add_edges(2,0,-(a[1]*2+1));add_edges(0,2,a[1]*2);
    add_edges(n,n-2,-(a[n]*2+1));add_edges(n-2,n,a[n]*2);
    for(int i=1;i<=n;i++){
        add_edges(i-1,i,1);
    }
    if(spfa()){
        a[1]=dist[1];
        for(int i=2;i<n+1;i++){
            a[i]=dist[i]-dist[i-1];
        }
        printf("%d",a[1]);
        for(int i=2;i<n+1;i++){
            printf(" %d",a[i]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/haohaoxuexilmy/article/details/88424323