[NOI1999] 01串


题目描述

  给定7个整数N,A0,B0,L0,A1,B1,L1,要求设计一个01串S=s1s2…si…sN,满足:
  1.si=0或si=1,1<=i<=N;
  2.对于S的任何连续的长度为L0的子串sjsj+1…sj+L0-1(1<=j<=N-L0+1),0的个数大于等于A0且小于等于B0;
  3.对于S的任何连续的长度为L1的子串sjsj+1…sj+L1-1(1<=j<=N-L1+1),1的个数大于等于A1且小于等于B1;
  例如,N=6,A0=1,B0=2,L0=3,A1=1,B1=1,L1=2,则存在一个满足上述所有条件的01串S=010101。


输入格式

仅一行,有7个整数,依次表示N,A0,B0,L0,A1,B1,L1(3<=N<=1000,1<= A0<=B0<=L0<=N,1<=A1<=B1<=L1<=N),相邻两个整数之间用一个空格分隔。


输出格式

仅一行,若不存在满足所有条件的01串,则输出一个整数-1,否则输出满足所有条件的01串中1的个数的最大值。


样例数据

样例输入

6 1 2 3 1 1 2

样例输出

3


说明

满足条件的01串为010101


题目分析


此题应有special judge,而市面上许多oj都没有加。
设二进制串为t[1…n]
设S[i]为t前i个字符中’1’的个数
显然后一位只能比前一位大1

SiSi11

Si1Si0

由题,0的个数大于等于A0且小于等于B0
可转化为1的个数大于等于L0-B0,小于等于L0-A0
于是有
Si1Si+L01B0L0

Si+L01Si1L0A0

Si1Si+L11A1

Si+L11Si1B1

因为全是小于符,差分约束跑一次最短路即可求出S[i]
再根据S[i]构造01序列


源代码

没有special judge的oj请不要按照我的代码写

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline const int Get_Int() {
    int num=0,bj=1;
    char x=getchar();
    while(x<'0'||x>'9') {
        if(x=='-')bj=-1;
        x=getchar();
    }
    while(x>='0'&&x<='9') {
        num=num*10+x-'0';
        x=getchar();
    }
    return num*bj;
}
const int maxn=2005;
struct Edge {
    int from,to,dist;
};
struct Difference_Constraints { //差分约束系统 
    int n,m;
    vectoredges;
    vector<int>G[maxn];
    bool inque[maxn];
    int dist[maxn],used[maxn];
    void init(int n) {
        this->n=n;
        edges.clear();
        for(int i=1; i<=n; i++)G[i].clear();
    }
    void AddEdge(int from,int to,int dist) {
        edges.push_back((Edge) {
            from,to,dist
        });
        m=edges.size();
        G[from].push_back(m-1);
    }
    void insert(int x,int y,int v) { //x-y<=v (flag=0),x-y>=v (flag=1)
        AddEdge(y,x,v);
    }
    bool spfa(int s) {
        for(int i=1; i<=n; i++)dist[i]=0x7fffffff/2;
        memset(inque,0,sizeof(inque));
        deque<int>Q;
        Q.push_back(s);
        dist[s]=0;
        inque[s]=1;
        used[s]++;
        while(!Q.empty()) {
            int Now=Q.front();
            Q.pop_front();
            inque[Now]=0;
            for(int i=0; iint Next=e.to;
                if(dist[Next]>dist[Now]+e.dist) {
                    dist[Next]=dist[Now]+e.dist;
                    if(!inque[Next]) {
                        used[Next]++;
                        if(used[Next]==edges.size())return false; //负权回环
                        if(!Q.empty()&&dist[Next]//SLF优化
                        else Q.push_back(Next);
                        inque[Next]=1;
                    } 
                }
            }
        }
        return true;
    }
    bool main(int Start) { //求出正整数解 
        if(spfa(Start)==0)return false;
        return true;
    }
};
Difference_Constraints dc; //全程小于符
int n,A0,B0,L0,A1,B1,L1; 
void Make() { //构造01序列 
    int cnt=0;
    for(int i=1; i<=n; i++) {
        if(cntputchar('1');
        } else putchar('0');
    }
    putchar('\n');
}
int main() {
    n=Get_Int();A0=Get_Int();B0=Get_Int();L0=Get_Int();A1=Get_Int();B1=Get_Int();L1=Get_Int();
    dc.init(n);
    for(int i=1; i<=n; i++) {
        dc.insert(i,i-1,1);
        dc.insert(i-1,i,0);
        if(i<=n-L0+1) {
            dc.insert(i-1,i+L0-1,B0-L0);
            dc.insert(i+L0-1,i-1,L0-A0);
        }
        if(i<=n-L1+1) {
            dc.insert(i-1,i+L1-1,-A1);
            dc.insert(i+L1-1,i-1,B1);
        }
    }
    if(dc.main(0)==0) {
        puts("-1");
        return 0;
    }
    Make();
    return 0;
}

你可能感兴趣的:(差分约束,最短路径)