zoukankan      html  css  js  c++  java
  • Luogu P1666 前缀单词

    题目传送门

    校内资格赛题目,差点高一就要( t{AFO})


    30分思路

    对30%的数据,满足(1≤n≤10)

    所以我们可以子集枚举,实际得分40pts

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int read(){
        int k=0; char c=getchar();
        for(;c<'0'||c>'9';) c=getchar();
        for(;c>='0'&&c<='9';c=getchar())
          k=k*10+c-48;
        return k;
    }
    char word[51][110];
    bool sa[51][51];
    long long ans;
    int main(){
        int n=read();
        for(int i=1;i<=n;i++) scanf("%s",word[i]);
        for(int i=1;i<=n;i++)
          for(int j=i;j<=n;j++){
          	bool flag=0;
          	int leni=strlen(word[i]),lenj=strlen(word[j]);
          	for(int pos=0;pos<=min(leni,lenj)-1;pos++){
          		if(word[i][pos]!=word[j][pos]){
          			flag=1; break;
                  }
            }
            if(!flag) sa[i][j]=sa[j][i]=1;
          }
        for(int i=1;i<=(1<<n)-1;i++){
        	//很奇怪的子集枚举
            int s[1010],tot=0,top=0,x=i;
            while(x){
                if(x&1) s[++top]=tot;
                x>>=1; tot++;
            }
            bool flag=0;
            for(int i=1;i<=top;i++){
                for(int j=i+1;j<=top;j++){
                  	if(sa[s[i]][s[j]]){
                  		flag=1; break;
                    }
                }
                if(flag) break;
            }
            if(!flag)  ans++;
        }
        cout<<ans+1;
        return 0;
    }
    

    正解

    我们先对单词排序,然后预处理出每两个之间是否是安全的,令dp[i]表示前(i)个单词中包含第(i)个单词的子集个数,如果(j<i)并且他们是安全的,dp[i]+=dp[j]。统计答案的时候,将(dp[i])累加起来就好了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int read(){
        int k=0; char c=getchar();
        for(;c<'0'||c>'9';) c=getchar();
        for(;c>='0'&&c<='9';c=getchar())
          k=k*10+c-48;
        return k;
    }
    string word[51];
    bool sa[51][51];
    long long ans,dp[110];
    int main(){
        int n=read();
        for(int i=1;i<=n;i++) cin>>word[i],dp[i]=1;
        sort(word+1,word+n+1);
        for(int i=1;i<=n;i++)
          for(int j=i;j<=n;j++){
          	bool flag=0;
          	int leni=word[i].size(),lenj=word[j].size();
          	for(int pos=0;pos<=min(leni,lenj)-1;pos++){
          		if(word[i][pos]!=word[j][pos]){
          			flag=1; break;
                  }
            }
            if(!flag) sa[i][j]=sa[j][i]=1;
          }
        for(int i=1;i<=n;i++)
          for(int j=i;j<=n;j++)
            dp[j]+=sa[i][j]? 0 : dp[i];
        for(int i=1;i<=n;i++) ans+=dp[i];
        cout<<ans+1;
    
        return 0;
    }
    
  • 相关阅读:
    A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
    Fliptile 开关问题 poj 3279
    Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276
    Aggressive cows 二分不仅仅是查找
    Cable master(二分题 注意精度)
    B. Pasha and String
    Intervals poj 1201 差分约束系统
    UITextField的快速基本使用代码块
    将UIImage转换成圆形图片image
    color转成image对象
  • 原文地址:https://www.cnblogs.com/morslin/p/11854890.html
Copyright © 2011-2022 走看看