福州大学第十四届程序设计竞赛_重现赛

这场是我有史以来第一次抢到全场FB,敲开森滴^_^
Ranklist

Pro.A Salty Fish
foj2253题目链接
最大子序列和的变形,注意题干中的“至少翻转一只咸鱼”

#include
#include
using namespace std;
int main()
{
    int n,i,x,a[100005],cnt,sum,mx;
    while(~scanf("%d",&n)){
        for(cnt=0,i=1;i<=n;i++){
            scanf("%d",&x),cnt+=x;  //cnt记录已经成功翻身的咸鱼数
            a[i]=x?-1:1;    //a数组记录的是将会对cnt产生的影响
        }
        sum=0;
        mx=-1;  //至少翻一条,所以mx的最小值是-1(当然也可以写cnt==n的特判continue)
        for(i=1;i<=n;i++){  //最大子序列和
            sum+=a[i];
            if(mxif(sum<0) sum=0;
        }
        printf("%d\n",cnt+mx);
    }
}

Pro.B 英语考试
foj2254题目链接
//比赛的时候一看是字符串题,就只能联想到字典树,kmp,马拉车,AC自动机,实在没啥想法就弃了
赛后听说是最小生成树(最短路也能做)
把每个单词都看作点,两点间的距离即汉明距离*w
引入一个点(可以想象为是下标为0的点,代码中做了些许简化),向另外n个点各连一条权值为m的边
稠密图用prim

#include
#include
#include
using namespace std;
#define N 1005
#define inf 0x3f3f3f3f
#define ms(x) memset(x,0,sizeof(x))
char s[N][15];
int mp[N][N],vs[N],dis[N],n,m;
int prim()
{
    int i,j,k,tmp,ret=0;
    for(i=1;i<=n;i++) vs[i]=0,dis[i]=m;
    for(i=1;i<=n;i++){
        for(tmp=inf,j=1;j<=n;j++)if(!vs[j]&&tmp>dis[j]) tmp=dis[j],k=j;
        ret+=tmp,vs[k]=1;
        for(j=1;j<=n;j++)if(!vs[j]) dis[j]=min(dis[j],mp[k][j]);
    }
    return ret;
}
int main()
{
    int w,i,j,k,tmp;
    while(~scanf("%d%d%d",&n,&m,&w)){
        for(i=1;i<=n;i++){
            scanf("%s",s[i]);
            for(j=1;jfor(tmp=0,k=0;kif(s[i][k]!=s[j][k]) tmp++;
                mp[i][j]=mp[j][i]=tmp*w;
            }
        }
        printf("%d\n",prim());
    }
}

Pro.D 迷宫
foj2256题目链接
层序遍历+搜一遍该点的祖先找到最小时间

#include
#include
#include
using namespace std;
#define N 100005
vector<int>V[N];
queue<int>Q;
__int64 ans[N],d[N],w[N];
int main()
{
    int n,f[N],i,p,u,v,sz;
    while(~scanf("%d",&n)){
        for(i=1;i<=n;i++) scanf("%I64d",&d[i]),f[i]=i,V[i].clear();
        for(i=2;i<=n;i++) scanf("%d%I64d",&p,&w[i]),f[i]=p,V[p].push_back(i);
        Q.push(1);
        while(!Q.empty()){
            u=Q.front(),Q.pop();
            sz=V[u].size();
            for(i=0;iwhile(p!=f[p]) p=f[p],ans[v]=min(ans[v],ans[p]+d[p]);
            }
        }
        for(i=1;i<=n;i++) printf("%I64d ",ans[i]);
        puts("");
    }
}

Pro.E Saya的小熊饼干
foj2257题目链接
(100分算法?):
考虑到期望的独立性,答案等于每个格子在k次操作中被粉刷过的概率之和
对于一个格子(i,j),设它一次就被刷到的概率为p,则它在k次中被至少刷到一次的概率为1-(1-p)^k
如何计算p呢?
由于两维是独立的,分开计算后根据乘法原理乘起来即可,p=px*py
那么只需要考虑一维的情况:
长度为n的序列中i一次就被刷到的概率=1-i一次都不被刷到的概率=1-((i-1)(i-1)+(n-i)(n-i))/n/n
注:
分母中n方表示n中任取两个点(可以是同一个点)
分子中(i-1)(i-1)表示两点都在i左侧,(n-i)(n-i)表示两点都在i右侧
这题与hdoj5245几乎完全一样

#include
#include
double cal(int i,int n)
{
    return 1-1.0*((i-1)*(i-1)+(n-i)*(n-i))/n/n;
}
int main()
{
    int k,n,m,i,j;
    while(~scanf("%d%d%d",&k,&n,&m)){
        double ans=0,p;
        for(i=1;i<=n;i++)for(j=1;j<=m;j++)
            p=cal(i,n)*cal(j,m),ans+=1-pow(1-p,k);
        printf("%.0f\n",ans);    //四舍五入,(int)是截尾取整
    }
}

Pro.F 奖励
foj2258题目链接

#include
int main()
{
    int n,cnt,a,b,c;
    while(~scanf("%d",&n)){
        cnt=0;
        while(n--){
            scanf("%d%d%d",&a,&b,&c);
            if(a<60||b<60||c<60) continue;
            if(a+b+c>=240) cnt++;
        }
        printf("%d\n",cnt);
    }
}

Pro.H Card Game
foj2260题目链接
用pre和nxt数组模拟链表,用队列模拟删的过程,复杂度O(n)

#include
#include
#include
using namespace std;
#define N 1000005
int a[N],pre[N],nxt[N],vs[N];
typedef pair<int,int>P;
queue

Q; int main() { int n,i,ans,u,v; while(~scanf("%d",&n)){ for(i=1;i<=n;i++){ scanf("%d",&a[i]),pre[i]=i-1,nxt[i]=i+1,vs[i]=0; if(a[i]1]) Q.push(P(i,1)),vs[i]=1; } ans=0; while(!Q.empty()){ P p=Q.front();Q.pop(); u=p.first,v=p.second; ans=max(ans,v); nxt[pre[u]]=nxt[u]; pre[nxt[u]]=pre[u]; if(pre[u]&&nxt[u]!=n+1&&!vs[nxt[u]]&&a[nxt[u]]1)),vs[nxt[u]]=1; } printf("%d\n",ans); for(i=1;i!=n+1;i=nxt[i]) printf("%d%c",a[i],nxt[i]==n+1?'\n':' '); } }

Pro.I 浪里个浪
foj2261题目链接
最短路,与hdoj2066类似,但数据更强
建立一个超级起点(下标为0),超级终点(下标为n+1)
超级起点向每个起点连一条权值为0的边,每个终点像超级终点连一条权值为0的边,跑单源最短路即可(代码中用的是spfa)

#include 
#include 
#include 
using namespace std;
#define N 100005
const int inf=0x7ffffff;
struct edge
{
    int to,w,nxt;
}e[N*3];
int head[N],t,vs[N],dis[N];
void add(int i,int j,int w)
{
    e[t].to=j;
    e[t].w=w;
    e[t].nxt=head[i];
    head[i]=t++;
}
void spfa(int s,int n)
{
    int i,u,v;
    queue<int>Q;
    for(i=0;i<=n;i++) dis[i]=inf,vs[i]=0;
    Q.push(s);
    dis[s]=0;
    while(!Q.empty()){
        u=Q.front(),Q.pop();
        vs[u]=0;
        for(i=head[u];i!=-1;i=e[i].nxt){
            v=e[i].to;
            if(dis[v]>dis[u]+e[i].w){
                dis[v]=dis[u]+e[i].w;
                if(!vs[v]) vs[v]=1,Q.push(v);
            }
        }
    }
}
int main()
{
    int n,m,i,u,v,w,x;
    while(~scanf("%d%d",&n,&m)){
        t=0;
        memset(head,-1,sizeof(head));
        while(m--) scanf("%d%d%d",&u,&v,&w),add(u,v,w);
        scanf("%d",&m);
        while(m--) scanf("%d",&x),add(0,x,0);
        scanf("%d",&m);
        while(m--) scanf("%d",&x),add(x,n+1,0);
        spfa(0,n+1);
        printf("%d\n",dis[n+1]);
    }
}

你可能感兴趣的:(FZU)