题解:P5751 [NOI1999] 01串
不容易呀,终于过了。
题目大意
给定 777 个整数 N,A0,B0,L0,A1,B1,L1N , A_0 , B_0 , L_0 , A_1 , B_1 , L_1N,A0,B0,L0,A1,B1,L1,要求构造 01 串 $ S=s_1 s_2 \dots s_i \dots s_N$,满足:
- si=0s_i = 0si=0 或 si=1s_i = 1si=1,1≤i≤N1 \leq i \leq N1≤i≤N;
- 对于 SSS 的任何连续的长度为 L0L_0L0 的子串 sjsj+1…sj+L0−1s_j s_{j+1} \dots s_{j+L0-1}sjsj+1…sj+L0−1(1≤j≤N−L0+11 \leq j \leq N-L_0+11≤j≤N−L0+1),000 的个数 A0≤cnt0≤B0A_0\leq cnt_0 \leq B_0A0≤cnt0≤B0;
- 对于 SSS 的任何连续的长度为 L1L_1L1 的子串 sjsj+1…sj+L1−1s_j s_{j+1} \dots s_{j+L1-1}sjsj+1…sj+L1−1(1≤j≤N−L1+11 \leq j \leq N-L_1+11≤j≤N−L1+1) ,111 的个数 A1≤cnt1≤B1A_1\leq cnt_1 \leq B_1A1≤cnt1≤B1。
分析
定义有 i∈Z∩[1,n]i \in Z \cap [1,n]i∈Z∩[1,n]。
记构造的 01 串 1 的前缀个数为 xi=∑j=1i(sj=1)x_i=\sum\limits_{j=1}^i(s_j=1)xi=j=1∑i(sj=1)。
基础条件(不论 A0,B0,L0,A1,B1,L1A_0,B_0,L_0,A_1,B_1,L_1A0,B0,L0,A1,B1,L1 的大小)
由题知 x0=0x_0=0x0=0,xi−xi−1≤1x_i-x_{i-1}\leq 1xi−xi−1≤1,xi−xi−1≥0⇒xi−1−xi≤0x_i-x_{i-1}\geq 0\Rightarrow x_{i-1}-x_i\leq 0xi−xi−1≥0⇒xi−1−xi≤0。
关于条件一
xi+L0−x+i≥L0−B0⇒xi−xi+L0≤B0−L0x_{i+L_0}-x+i\geq L_0-B_0\Rightarrow x_i-x_{i+L_0}\leq B_0-L_0xi+L0−x+i≥L0−B0⇒xi−xi+L0≤B0−L0
xi+L0−x+i≤L0−A0x_{i+L_0}-x+i\leq L_0-A_0xi+L0−x+i≤L0−A0
关于条件二
xi+L1−x+i≥A1⇒xi−xi+L0≤−A1x_{i+L_1}-x+i\geq A_1\Rightarrow x_i-x_{i+L_0}\leq -A_1xi+L1−x+i≥A1⇒xi−xi+L0≤−A1
xi+L1−x+i≤B1x_{i+L_1}-x+i\leq B_1xi+L1−x+i≤B1
得到如上关系后,差分约束即可。
Code(不可以抄)
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e3+1;
vector<pair<int,int> >G[MAXN+1];
int cnt[MAXN+1],vis[MAXN+1];
long long dist[MAXN+1];
int n,a0,b0,l0,a1,b1,l1;
void SPFA(void){
memset(dist,0x3f,sizeof dist);
memset(vis,0,sizeof vis);
queue<int>Q;
Q.push(0);
dist[0]=0;vis[0]=1;
while(!Q.empty()){
int F=Q.front();Q.pop();
for(auto i:G[F]){
int T=i.first,w=i.second;
if(dist[T]>dist[F]+w){
dist[T]=dist[F]+w;
cnt[T]=cnt[F]+1;
if(cnt[T]>=n){
cout<<"-1\n";
exit(0);
}
if(!vis[T]){
vis[T]=1;
Q.push(T);
}
}
}
vis[F]=false;
}
return;
}
int main(){
scanf("%d%d%d%d%d%d%d",&n,&a0,&b0,&l0,&a1,&b1,&l1);
for(int i=1;i<=n;i++){
G[i].push_back(make_pair(i-1,0));
G[i-1].push_back(make_pair(i,1));
G[n+1].push_back(make_pair(0,0));
}
for(int i=l0;i<=n;i++){
G[i].push_back(make_pair(i-l0,b0-l0));
G[i-l0].push_back(make_pair(i,l0-a0));
}
for(int i=l1;i<=n;i++){
G[i].push_back(make_pair(i-l1,-a1));
G[i-l1].push_back(make_pair(i,b1));
}
SPFA();
cout<<dist[n];
return 0;
}

被折叠的 条评论
为什么被折叠?



