NOIP2017金秋冲刺训练营杯联赛模拟大奖赛Day2
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2017金秋冲刺训练营杯联赛模拟大奖赛Day2相关的知识,希望对你有一定的参考价值。
T1
模拟+排序,先把n个公司贪成合法,再在剩下的天数中找最大值
注意不要统计2-t<0的天数
1 #include <cstdio> 2 #include <vector> 3 #include <iostream> 4 #include <algorithm> 5 #define ll long long 6 using namespace std; 7 long long n,m,s,k,e,t,sz,j,flag=0,ans=0,cnt[200001],del[200001]; 8 vector<long long> cop[200001],all; 9 bool cmp(long long a,long long b){return a>b;} 10 int main() 11 { 12 freopen("express.in","r",stdin); 13 freopen("express.out","w",stdout); 14 cin>>n>>m>>s>>k; 15 for (long long i=1;i<=m;i++) 16 { 17 cin>>e>>t; 18 if (2-t<0) cop[e].push_back(t-2); 19 } 20 for (long long i=1;i<=n;i++) 21 { 22 sort(cop[i].begin(),cop[i].end(),cmp); 23 sz=cop[i].size(),j=0; 24 while(j<sz&&s>0&&cnt[i]<k) cnt[i]+=cop[i][j],ans+=cop[i][j],j++,s--; 25 while(j<sz) all.push_back(cop[i][j]),j++; 26 if (cnt[i]<k) flag=1; 27 } 28 if (flag==1){cout<<"-23333333"<<endl;return 0;} 29 sort(all.begin(),all.end(),cmp); 30 sz=all.size(),j=0; 31 while(s>0&&j<sz) ans+=all[j],j++; 32 cout<<ans<<endl; 33 }
T2
DFS
碰到括号的时候就递归从括号的另一端反向搜索,直到读到括号结尾递归返回上一层
1 #include <cstdio> 2 #include <cstring> 3 char s[500001]; 4 int len,dep=0,dep2pos[500001],to[500001]; 5 void putans(int x,int f) 6 { 7 while(1) 8 { 9 if (x==len) return; 10 if (f==1&&s[x]==‘)‘) return; 11 if (f==-1&&s[x]==‘(‘) return; 12 if (s[x]==‘(‘||s[x]==‘)‘) 13 { 14 putans(to[x]-f,-f); 15 x=to[x]; 16 }else printf("%c",s[x]); 17 x+=f; 18 } 19 } 20 int main() 21 { 22 freopen("unknown.in","r",stdin); 23 freopen("unknown.out","w",stdout); 24 scanf("%s",s); 25 len=strlen(s); 26 for (int i=0;i<len;i++) 27 { 28 if (s[i]==‘(‘) 29 { 30 dep++; 31 dep2pos[dep]=i; 32 } 33 if (s[i]==‘)‘) 34 { 35 to[i]=dep2pos[dep]; 36 to[dep2pos[dep]]=i; 37 dep--; 38 } 39 } 40 putans(0,1); 41 }
T3
状压DP,可惜考试的时候写崩了QWQ(果然是自己平时状压DP写的太少了),考试结束后用了40分钟才找出这3个隐蔽的错误
这个DP还可以接着优化,提前把所有状态按包含1的数量排序,就可以直接递推了,并且每个状态只能从含1数比它少的状态转移,所以复杂度是$O(2^2n/2)$,大概能拿70分
如果转移的时候配合dfs应该能拿满分
看来以后要想一个更好的方法来查找bug……
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 int n,m,kw,a,b,f[1<<16],e[16][16],cnt1[1<<16],cnte[1<<16]; 6 int cntone(int state) 7 { 8 int s=0; 9 while(state!=0) 10 { 11 s+=state&1; 12 state=state>>1; 13 } 14 return s; 15 } 16 int check(int s1,int s2) 17 { 18 int s=1; 19 for (int i=0;i<n;i++) 20 { 21 if ((s1&(1<<i)==0)&&(s2&(1<<i)==0)) s=0; 22 } 23 return s; 24 } 25 int cntedge(int state) 26 { 27 int s=0; 28 for (int i=0;i<n;i++) 29 for (int j=0;j<n;j++) 30 if ((state&(1<<i))&&(state&(1<<j))) s+=e[i][j]; 31 return s; 32 } 33 int main() 34 { 35 freopen("prison.in","r",stdin); 36 freopen("prison.out","w",stdout); 37 //int n,m,k 12:21错把n,m,k声明成局部变量 38 scanf("%d%d%d",&n,&m,&kw); 39 for (int i=1;i<=m;i++) 40 { 41 scanf("%d%d",&a,&b); 42 e[a-1][b-1]=1; 43 } 44 memset(f,0x7f,sizeof(f)); 45 f[0]=0; 46 for (int i=0;i<(1<<n);i++) cnt1[i]=cntone(i); 47 for (int i=0;i<(1<<n);i++) cnte[i]=cntedge(i); 48 for (int i=1;i<=n;i++)//已经选择i个人 49 { 50 for (int j=0;j<(1<<n);j++)//末状态 51 if (cnt1[j]==i) 52 for (int k=0;k<(1<<n);k++)//初状态 53 { 54 if (check(j,k)==0) continue;//12:36错把continue写成break 55 if (cnte[j-k]>kw) continue;//12:36错把continue写成break 56 f[j]=min(f[j],f[k]+1); 57 } 58 } 59 printf("%d",f[(1<<n)-1]); 60 }
以上是关于NOIP2017金秋冲刺训练营杯联赛模拟大奖赛Day2的主要内容,如果未能解决你的问题,请参考以下文章
TYVJ NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第二轮Day2题解