一道很灵活的贪心小题木,我也是看了官方题解才想到的- -!!一般都用最大流做的。
枚举+贪心构造法
#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"); } } }