一道很灵活的贪心小题木,我也是看了官方题解才想到的- -!!一般都用最大流做的。
枚举+贪心构造法
#include <cstdio>
#include <cstring>
using namespace std;
int T,N;
char com[1001][2];
int id[1001];
bool in[5001];
bool oc[5001];
int sot[5001];
int ID=2001;
bool simulate(int n){
for(int i=0; i<n; ++i){
bool sta=0;
memset(oc,0,sizeof(oc));
for(int j=0; j<N; ++j){
if(com[j][0]=='L'&&oc[id[j]]==0&&id[j]&&in[id[j]]==0){
in[id[j]]=1;
sta=1;
break;
}
oc[id[j]]=1;
}
if(sta==0){
in[ID++]=1;
}
}
for(int i=0; i<N; ++i){
if(com[i][0]=='E'){
if(id[i]==0){
bool sta=0;
memset(oc,0,sizeof(oc));
for(int j=i+1; j<N; ++j){
if(com[j][0]=='L'&&oc[id[j]]==0&&id[j]&&in[id[j]]==0){
in[id[j]]=1;
sta=1;
break;
}
oc[id[j]]=1;
}
if(sta==0){
in[ID++]=1;
}
}else{
if(in[id[i]]){
return false;
}else{
in[id[i]]=1;
}
}
}else{
if(id[i]==0){
bool sta=0;
memset(oc,0,sizeof(oc));
for(int j=i+1; j<N; ++j){
if(com[j][0]=='E'&&oc[id[j]]==0&&id[j]&&in[id[j]]){
in[id[j]]=0;
sta=1;
break;
}
oc[id[j]]=1;
}
if(sta==0){
memset(oc,0,sizeof(oc));
for(int j=i+1; j<N; ++j){
if(id[j]){
oc[id[j]]=1;
}
}
for(int j=1; j<=5000; ++j){
if(in[j]&&oc[j]==0){
in[j]=0;
sta=1;
break;
}
}
}
if(sta==0){
memset(sot,0,sizeof(sot));
for(int j=N-1; j>i; --j){
if(com[j][0]=='L'&&in[id[j]]){
sot[id[j]]=j;
}
}
int tmp=0,iid=-1;
for(int j=1; j<=5000; ++j){
if(sot[j]>tmp){
iid=j; tmp=sot[j];
}
}
if(iid!=-1){
in[iid]=0; sta=1;
}
}
if(sta==0) return false;
}else{
if(in[id[i]]==0){
return false;
}else{
in[id[i]]=0;
}
}
}
}
return true;
}
int main(){
freopen("C-large-practice.in","r",stdin);
freopen("c2.out","w",stdout);
scanf("%d",&T);
for(int cas=1; cas<=T; ++cas){
scanf("%d",&N);
int icnt=0,ocnt=0;
for(int i=0; i<N; ++i){
scanf("%s %d",com+i,id+i);
if(com[i][0]=='E') ++icnt;
else ++ocnt;
}
printf("Case #%d: ",cas);
bool end=0;
for(int i=0; i<=N; ++i){
ID=2001;
memset(in,0,sizeof(in));
if(simulate(i)){
printf("%d\n",icnt+i-ocnt);
end=1;
break;
}
// puts("CRIME TIME");
}
if(end==0){
puts("CRIME TIME");
}
}
}