NOIP2017提高组 模拟赛23(总结)

来源:互联网 发布:mac怎么删除硬盘文件 编辑:程序博客网 时间:2024/05/22 14:11

NOIP2017提高组 模拟赛23(总结)

第一题 Hacker

【题目描述】

【解题思路】

  只需要两段假期,而且天数也不会超过10^6。直接用数组记下就好。排个序,遇头统计前面的是否有符合的,遇尾就把这段假期加进数组里。

【代码】

#include<cstdio>#include<algorithm>#define imin(a,b) ((a<b)?(a):(b))using namespace std;const int N=1000100;const int oo=1000000100;int n,m,n2,ans;int L[N],R[N],X[N],mm[N];struct data { int x,id; bool fl; } d[N<<1];bool cmp(data A,data B) { return (A.x<B.x || (A.x==B.x && (A.fl==0 && B.fl==1))); }int main(){    freopen("1982.in","r",stdin);    freopen("1982.out","w",stdout);    scanf("%d%d",&n,&m);    for(int i=0;i<=m;i++) mm[i]=oo;    for(int i=1;i<=n;i++)    {        scanf("%d%d%d",&L[i],&R[i],&X[i]);        d[i].id=i; d[i].x=L[i]; d[i].fl=0;        d[i+n].id=i; d[i+n].x=R[i]; d[i+n].fl=1;    }    n2=n<<1;    sort(d+1,d+1+n2,cmp);    ans=oo<<1;    for(int i=1;i<=n2;i++)    {        int id=d[i].id;        int len=R[id]-L[id]+1;        if(d[i].fl==1) mm[len]=imin(mm[len],X[id]); else        {            if(len>=m) continue;            if(mm[m-len]!=oo) ans=imin(ans,mm[m-len]+X[id]);        }    }    printf("%d\n",(ans==(oo<<1))?(-1):(ans));    return 0;}

第二题 记字符串 (状压DP)

【题目描述】

【解题思路】

  字符串的长度和个数都不超过20。
  假如,要用第i位来使第i位相同的字符串独立,有两种情况:
  ①将所有相同的字符改成其他字符,最大的不用改。
  代价=所有第i位相同的字符串改第i位的代价的总和-字符串改第i位的最大代价。
  ②还有一种就是改单个字符。
  代价=最小的改一位的代价(从1~m位中改最小代价的那一位)。
  因为只有20个字符串,一定可以改成与其他字符不同的字符。
  状态压缩DP。
  记现在处理到第w位,已经独立的字符串的状态为S的最小代价。
  预处理出将第i个字符串的第j位改掉(用① 的改法),所影响的字符串集合Wij.S,代价为Wij.cost。
  还有第②中改法的单个字符串i最小代价mn[i]。
  找出S的未被独立的最小的i。
  ①枚举改第j位。F[S|Wij.S]=min(F[S|Wij.S],F[S]+Wij.cost)
  ②F[S|(1<<(i1))]=min(F[S|(1<<(i1))],F[S]+mn[i])

【代码】

#include<cstdio>#include<cstring>#include<algorithm>#define imax(a,b) ((a>b)?(a):(b))#define imin(a,b) ((a<b)?(a):(b))#define fn (1<<n)using namespace std;const int inf=1e9;const int N=25;const int big=1500000;int n,m;struct data { int stu,cs; } w[N][N];int cs[N][N],d[N][N],f[big],mn[N];char st[N];int main(){    freopen("1983.in","r",stdin);    freopen("1983.out","w",stdout);    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%s",st);        for(int j=0;j<m;j++) d[i][j+1]=st[j]-'a'+1;    }    for(int i=1;i<=n;i++)    {        mn[i]=inf;        for(int j=1;j<=m;j++) scanf("%d",&cs[i][j]),mn[i]=imin(mn[i],cs[i][j]);    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            int ysum=0,mx=0;            int stu=0;            for(int h=1;h<=n;h++)            if(d[h][j]==d[i][j])            {                stu+=(1<<(h-1));                ysum+=cs[h][j];                mx=imax(mx,cs[h][j]);            }            w[i][j].stu=stu;            w[i][j].cs=ysum-mx;        }    }    for(int i=1;i<fn;i++) f[i]=inf;    f[0]=0;    for(int i=0;i<fn;i++)    if(f[i]!=inf)    {        int last=0;        while(i&(1<<last)) last++;        if(last>=n) continue;        int yu;        for(int j=1;j<=m;j++)        {            yu=i|(w[last+1][j].stu);            f[yu]=imin(f[yu],f[i]+w[last+1][j].cs);        }        yu=i|(1<<(last));        f[yu]=imin(f[yu],f[i]+mn[last+1]);    }    printf("%d\n",f[fn-1]);    return 0;}

第三题 士兵与旅行 (网络流)

【题目描述】

【解题思路】

  城市和道路构成一幅图,每一个城市的士兵只能去相邻的城市。一开始的状态为S1,结束状态为S2。
  先在需要从S1转到S2。
  可以对每一个城市建立两个点Ai,Bi,分别表示转移之前的和转移之后的。
  若城市i可以到达城市j,则Ai->Bj,流量无穷大。(因为士兵可以从i转移到j,流了多少就表示转移多少)
  从源点S->城市i,流量为一开始城市i的士兵数。
  城市i->汇点T,流量为转移之后的士兵数。
  判断流出流量是否等于流入流量就好。
  若等于,则一定存在转移方案。城市Ai->城市Bj的反向边的流量就是转移方案(因为记录的是剩余流量,开始为∞,流了w,变成∞-w。那么反向边的流量就是w)。

【代码】

#include<cstdio>#include<algorithm>#define imax(a,b) ((a>b)?(a):(b))#define imin(a,b) ((a<b)?(a):(b))#define ad(i) (i)#define bd(i) (n+i)using namespace std;const int inf=1e9;const int N=120;const int M=220;const int maxm=1000000;int n,m,sum_a,sum_b;int A[N],B[N];int bfstime,q[maxm],lev[maxm],vis[maxm];int h[maxm],d0,S,T;int yu[N][N];struct data { int val,to,ne; } d[maxm];void addedge(int a,int b,int c){    d0++;    d[d0].to=b;d[d0].val=c;d[d0].ne=h[a];h[a]=d0;    d0++;    d[d0].to=a;d[d0].val=0;d[d0].ne=h[b];h[b]=d0;}bool bfs(){    int head=1,tail=1;    q[head]=S;    vis[S]=++bfstime;    lev[S]=1;    while(head<=tail)    {        for(int p=h[q[head]];p;p=d[p].ne)        {            if(!d[p].val) continue;            int to=d[p].to;            if(vis[to]==bfstime) continue;            q[++tail]=to;            vis[to]=bfstime;            lev[to]=lev[q[head]]+1;        }        head++;    }    return vis[T]==bfstime;}int dfs(int now,int maxf){    int ret=0,t;    if(now==T || !maxf ) return maxf;    for(int p=h[now];p;p=d[p].ne)    {        int to=d[p].to;        if(!d[p].val || lev[to]!=lev[now]+1) continue;        t=dfs(to,imin(maxf,d[p].val));        d[p].val-=t;        d[p^1].val+=t;        maxf-=t;        ret+=t;    }    if(maxf) lev[now]=-1;    return ret;}int dinic(){    int ret=0;    while(bfs()) ret+=dfs(S,1e9);    return ret;}int main(){    freopen("1984.in","r",stdin);    freopen("1984.out","w",stdout);    scanf("%d%d",&n,&m); d0=1;    S=(n<<1)+1; T=S+1;    sum_a=sum_b=0;    for(int i=1;i<=n;i++)    {        scanf("%d",&A[i]);        addedge(S,ad(i),A[i]);        sum_a+=A[i];    }    for(int i=1;i<=n;i++)    {        scanf("%d",&B[i]);        addedge(bd(i),T,B[i]);        addedge(ad(i),bd(i),inf);        sum_b+=B[i];    }    for(int i=1;i<=m;i++)    {        int a,b; scanf("%d%d",&a,&b);        addedge(ad(a),bd(b),inf);        addedge(ad(b),bd(a),inf);    }    int sum_la=dinic();    if(sum_la==sum_b)    {        printf("YES\n");        for(int i=1;i<=n;i++)        {            int u=bd(i);            for(int p=h[u];p;p=d[p].ne)            {                if(!(p&1)) continue;                int to=d[p].to;                yu[to][i]+=d[p].val;            }        }        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++) printf("%d ",yu[i][j]);            printf("\n");        }    } else printf("NO\n");    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 婴儿身上长癣怎么办 婴儿下巴口水藓怎么办 婴儿嘴边长癣怎么办 婴儿脸上口水癣怎么办 嘴巴旁边长癣怎么办 美团机票不出票怎么办 东方航空会员锁定怎么办 大众车烧机油怎么办 大众cc烧机油怎么办 叫外卖给差评被打怎么办 发现宿舍被盗后怎么办 知了猴变黑了怎么办 婴儿仙人掌的刺怎么办 仙人掌刺扎进皮肤里怎么办 被仙人掌的小细绒刺扎到怎么办 值机截止了怎么办 社保卡消磁了怎么办 住宾馆没身份证怎么办 社保卡电话错误怎么办 没住过酒店怎么办 上海合规网约车证件怎么办 取票没有身份证怎么办 买车票没有身份证怎么办 登机身份证丢了怎么办 飞机没带身份证怎么办 上飞机没带身份证怎么办 机场没带身份证怎么办 儿童坐飞机没有户口本怎么办 不需要行李托运化妆品怎么办 坐飞机被限制了怎么办 坐飞机没买保险怎么办 飞机起飞时难受怎么办 婴儿坐飞机没座位怎么办 转机行李不直达怎么办 儿童自己坐飞机怎么办手续 两岁宝宝发烧怎么办 网上购票待核验怎么办 老人坐飞机找不到登机口怎么办 儿童不能值机怎么办 飞机上旅客刁难怎么办 飞机上婴儿哭闹怎么办