[考试反思]1013csp-s模拟测试71:徘徊

分差好大。。。但是从排名上看也许还可以接受?

不算太炸

但是这个还是算了吧。。。

其实状态不是很好。

T1不会,打的搜索,想到一个剪枝但是感觉没什么用,所以没打。

考后打上,85了。。。打上另一个就90了。。。

T3已经想到正解思路了,但是不完善

T2想到正解,但是没有证明它是树形,于是没有打。。。

又说不完,晚上又要考,改善状态。

 

T1:毛一琛

又是meet in miiddle。又没想到。

其实也就是双向搜索,然后hash_map查状态即可。

打的lower_bound,多了一个log。勉强过了。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 vector<int>X[1025],Y[1025];
 6 int n,x[22],ans,y[1048577],r;
 7 void sch1(int p,int w,int st){
 8     if(p-1==n>>1){if(w>=0)X[st].push_back(w);return;}
 9     sch1(p+1,w-x[p],st|1<<p-1);sch1(p+1,w,st);sch1(p+1,w+x[p],st|1<<p-1);
10 }
11 void sch2(int p,int w,int st){
12     if(p==n+1){if(w>=0)Y[st].push_back(w);return;}
13     sch2(p+1,w+x[p],st|1<<p-r);sch2(p+1,w,st);sch2(p+1,w-x[p],st|1<<p-r);
14 }
15 int main(){
16     scanf("%d",&n);
17     for(int i=1;i<=n;++i)scanf("%d",&x[i]);r=(n>>1)+1;
18     sch1(1,0,0);sch2(r,0,0);
19     for(int i=0;i<1<<(n>>1);++i)sort(X[i].begin(),X[i].end());
20     for(int i=0;i<1<<n-(n>>1);++i)sort(Y[i].begin(),Y[i].end());
21     for(int i=0;i<1<<(n>>1);++i)for(int j=0;j<1<<n-(n>>1);++j)
22         for(int v=0;v<X[i].size();++v)
23             if(lower_bound(Y[j].begin(),Y[j].end(),X[i][v])!=Y[j].end())
24                 if(*(lower_bound(Y[j].begin(),Y[j].end(),X[i][v]))==X[i][v])
25                     y[i<<n-(n>>1)|j]=1;
26     for(int i=1;i<1<<n;++i)ans+=y[i];//,printf("%d\n",y[i]);
27     printf("%d\n",ans);
28 }
View Code

 

T2:毛二琛

首先这题puts("0")会爆零,所以所有情况都有解。

考虑每一个数移动的方向,那么其实就限制了q序列上某两个相差为1的值的相对位置。

这样的话就是SAO那道题简化到序列上了,dp[i][j]表示考虑到操作i,其相对位置是j,前缀和优化就完事了。

代码倒好说。想到就能写出来。

 1 #include<cstdio>
 2 #define mod 1000000007
 3 inline int Mod(int p){return p>=mod?p-mod:p;}
 4 int p[5005],np[5005],n,dir[5005],dp[5005][5005],sum[5005][5005];//dir=2先i后i-1
 5 int main(){
 6     scanf("%d",&n);
 7     for(int i=1;i<=n;++i)scanf("%d",&p[i]),p[i]++,np[p[i]]=i;
 8     for(int i=1;i<=n;++i)
 9         if(np[i]>i){dir[i]=2;for(int j=i+1;j<p[i];++j)dir[j]=1;}
10         else {dir[i]=1;for(int j=i-1;j>np[i];--j)dir[j]=2;}
11     dp[1][1]=sum[1][1]=1;
12     for(int i=2;i<=n-1;++i){
13         if(dir[i]==2)for(int j=1;j<=i;++j)dp[i][j]=Mod(mod+sum[i-1][i-1]-sum[i-1][j-1]);
14         else for(int j=1;j<=i;++j)dp[i][j]=sum[i-1][j-1];
15         for(int j=1;j<=i;++j)sum[i][j]=Mod(sum[i][j-1]+dp[i][j]);
16     }printf("%d\n",sum[n-1][n-1]);
17 }
View Code

 

T3:毛三琛

二分答案,剪枝,及时跳出。

如果目前的x连目前最优答案都不到,continue。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,k,p,a[10005],ans=1000000000;
 4 int Mod(int x){return x>=p?x-p:x;}
 5 int chk(int w,int xx){
 6     int al=1,f=0;
 7     for(int i=1;i<=n&&al<=k;++i){int x=Mod(xx+a[i]);if(x>w)return 0;if(f+x>w)al++,f=x;else f+=x;}
 8     if(al<=k)return 1;
 9     return 0;
10 }
11 int main(){
12     scanf("%d%d%d",&n,&p,&k);
13     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
14     for(int i=0;i<p;++i){
15         if(!chk(ans,i))continue;
16         register int l=0,r=ans;
17         while(l<r-1)if(chk(l+r>>1,i))r=l+r>>1;else l=(l+r>>1)+1;
18         ans=min(ans,chk(l,i)?l:r);
19     }
20     printf("%d\n",ans);
21 }
View Code

 

posted @ 2019-10-13 18:20  DeepinC  阅读(242)  评论(2编辑  收藏  举报