zoukankan      html  css  js  c++  java
  • 2019.9.20 csp-s模拟测试48 反思总结

    头疼,不说废话了,祝大家rp++。

    T1:

    暴力枚举,n3

    枚举两个串开始匹配的位置,每一次尽量修改。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,k,cnt,num,ans;
    char a[310],b[310];
    int main()
    {
        scanf("%d%d",&n,&k);
        scanf("%s",a+1);
        scanf("%s",b+1);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cnt=0,num=0;
                for(int l=i,r=j;l<=n&&r<=n;l++,r++){
                    if(a[l]!=b[r])cnt++;
                    if(cnt>k)break;
                    num++;
                }
                ans=max(ans,num);
            }
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    T2:

    枚举四个点中间的两个点,它们对应的路径条数就是度数减一的乘积,即(du[i]-1)*(du[j]-1)。减一是因为它们彼此相连。

    然后还要考虑重复的情况,即它们走到同一个点。因为一条满足条件的链节点数只有四,重复的情况只可能是它们两个第一步走出去的点是同一个点,即两个点都和那个重复点直接相连,这种时候答案多统计了一次。可以用bitset存每个点连出去的节点,答案减去交集的大小。

    听他们说这个是三元环计数……?不知道不了解,之后补课。

    因为我不会用bitset,考场上全靠自己根据一点模糊印象瞎搞,一开始给bitset开出的100000的大小到最后也没改,然后t成了40分。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<bitset>
    using namespace std;
    int n,d[1510];
    long long ans;
    bitset<1510>s[1510];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            for(int j=1,x;j<=n;j++){
                scanf("%1d",&x);
                if(x)s[i][j]=1,d[i]++;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i!=j&&s[i][j]){
                    ans+=(d[i]-1)*(d[j]-1);
                    ans-=(s[i]&s[j]).count();
                }
            }
        }
        printf("%lld",ans);
        return 0;
    }
    View Code

    T3:

    首先考虑枚举每个val的子集连0边,然后每个点向对应权值连1边,再由权值向这个点连0边。这就好像出发的起始费用是1,走到另一个节点的结尾收费是0,于是每条路全长为1。

    发现这样连出来的图,很多节点都能到达同一个节点,然而这些节点彼此之间也存在到达的关系。可以考虑让一个点不会到达“可以到达的点”会到达的点,即减少边数,让能被传递的到达关系尽量代替直接到达关系。那么只要让每个权值连向它的某一位去掉1的值就可以了。原本存在的节点与权值连的两条边不变,题目给出的m条边也不变,最后边数变成了20*220+2n+m。

    因为边权只存在1和0,直接跑双端队列bfs,每一次要把能0边到达的所有点都加进队列保证距离不减。挺丢人的,我没太弄明白最后这句,后来一想bfs每个点只到达一次,可不是要尽量更早到达吗……

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<set>
    #include<cmath>
    #include<queue>
    using namespace std;
    const int inf=2147483647;
    const int maxn=(1<<20);
    deque<pair<int,int> >q;
    long long d[2000005];
    int n,m,t,cnt=maxn,num,p,sum;
    int a[2000005],vis[2000005];
    int ver[2000005],Next[5000005],tot,head[5000005],edge[5000005];
    void add(int x,int y,int z){
        ver[++tot]=y;
        Next[tot]=head[x];
        head[x]=tot;
        edge[tot]=z;
    }
    void bfs(){
        d[maxn+1]=0;
        q.clear();
        vis[1+maxn]=1;
        q.push_back(make_pair(1+maxn,0));
        while(!q.empty()){
            int x=q.front().first;
            d[x]=q.front().second;
            q.pop_front();
            if(x<=maxn){
                for(int j=0;j<=20;j++){
                    if((x&(1<<j))&&!vis[x^(1<<j)]){
                        vis[x^(1<<j)]=1;
                        q.push_front(make_pair(x^(1<<j),d[x]));
                    }
                }
                if(!vis[0]){
                    q.push_front(make_pair(0,d[x]));
                    vis[0]=1;
                }
            }
            for(int i=head[x];i;i=Next[i]){
                int y=ver[i];
                if(!vis[y]){
                    vis[y]=1;
                    if(edge[i])q.push_back(make_pair(y,d[x]+1));
                    else q.push_front(make_pair(y,d[x]));
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            add(maxn+i,a[i],0);
            add(a[i],maxn+i,1);
        }
        for(int i=1,x,y;i<=m;i++){
            scanf("%d%d",&x,&y);
            add(x+maxn,y+maxn,1);
        }
        for(int i=0;i<=maxn+n;i++)d[i]=-1;
        bfs();
        for(int i=maxn+1;i<=maxn+n;i++){
            printf("%lld
    ",d[i]);
        }
        return 0;
    }
    写错一句位运算调了一早晨

    又没去学校,苟在家里改题。身体状况略有点可笑,因为状态差所以不得不想一些办法来让自己打起精神,但是这么做的话身体就会更差,最后索性放弃治疗。能活多久就多久吧,最少撑两个月就行。

    活着还是死去有什么区别呢。

  • 相关阅读:
    String 类的常用方法都有那些?
    ArrayList、LinkedList、Vector 的区别。
    1.JDK,JRE,JVM三者关系
    ==与equals的区别
    [LeetCode#22]Generate Parentheses
    [LeetCode#20]Valid Parentheses
    [LeetCode#2]Add Two Numbers
    [LeetCode#1] Two Sum
    [LeetCode#9] Palindrome Number
    [LeetCode#7]Reverse Integer
  • 原文地址:https://www.cnblogs.com/chloris/p/11562259.html
Copyright © 2011-2022 走看看