BZOJ3170~3172 TJOI2013 DAY1

来源:互联网 发布:淘宝达人一万粉丝 编辑:程序博客网 时间:2024/03/28 19:07

T1松鼠聚会

求切比雪夫距离之和最小。
要去的点在“中间”,于是我就算算中间的点就过了 。

#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<cmath>#include<algorithm>using namespace std;#define LL long longconst int maxn = 100005;struct node{    int x,y;}a[maxn];LL dis(node a,node b){    LL dx=abs(a.x-b.x);    LL dy=abs(a.y-b.y);    return max(dx,dy);}int n;LL ans,sum;bool cmp1(node a,node b){    return a.x<b.x;}bool cmp2(node a,node b){    return a.y<b.y;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d%d",&a[i].x,&a[i].y);    if(n<1000){        ans=1ll<<60,sum;        for(int i=1;i<=n;i++){            sum=0;            for(int j=1;j<=n;j++)sum+=dis(a[i],a[j]);            ans=min(ans,sum);        }    }else{        sort(a+1,a+1+n,cmp1);        ans=1ll<<60,sum;        int mid=(1+n)>>1;        for(int i=mid-100;i<=mid+100;i++){            sum=0;            for(int j=1;j<=n;j++)sum+=dis(a[i],a[j]);            ans=min(ans,sum);        }        sort(a+1,a+1+n,cmp2);        for(int i=mid-100;i<=mid+100;i++){            sum=0;            for(int j=1;j<=n;j++)sum+=dis(a[i],a[j]);            ans=min(ans,sum);        }    }    printf("%lld\n",ans);}

T2循环格

供求平衡问题,费用流解决

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<queue>using namespace std;const int maxn = 2005;const int mx[]={1,0,-1,0};const int my[]={0,1,0,-1};const char ch[]={'D','R','U','L'};struct edge{    int x,y,next,v,c;    edge(){}    edge(int _x,int _y,int _nt,int _v,int _c)    :x(_x),y(_y),next(_nt),v(_v),c(_c){}}e[maxn<<1];int head[maxn],tot=1;void addedge(int x,int y,int v,int c){    e[++tot]=edge(x,y,head[x],v,c);head[x]=tot;    e[++tot]=edge(y,x,head[y],0,-c);head[y]=tot;}int n,m,S,T=0;int num[20][20],dis[maxn],fro[maxn];bool inq[maxn];queue<int>q;bool SPFA(){    for(int i=S;i<=T;i++)dis[i]=0x3f3f3f3f;    dis[S]=0;q.push(S);inq[S]=1;    while(!q.empty()){        int x=q.front();q.pop();inq[x]=0;        for(int y,v,c,i=head[x];i;i=e[i].next){            y=e[i].y;v=e[i].v;c=e[i].c;            if(v && dis[y]>dis[x]+c){                dis[y]=dis[x]+c;                fro[y]=i;                if(!inq[y]){                    inq[y]=1;q.push(y);                }            }        }    }    return dis[T]!=0x3f3f3f3f;}int mcf(){    int ret=0;    while(SPFA()){        int tmp=0x3f3f3f3f;        for(int i=fro[T];i;i=fro[e[i].x])tmp=min(tmp,e[i].v);        ret+=tmp*dis[T];        for(int i=fro[T];i;i=fro[e[i].x])e[i].v-=tmp,e[i^1].v+=tmp;    }    return ret;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)        num[i][j]=++T;    char str[20];    for(int i=1;i<=n;i++){        scanf("%s",str+1);        for(int j=1;j<=m;j++){            for(int k=0;k<4;k++){                int x=i+mx[k];if(x>n)x=1;if(x<1)x=n;                int y=j+my[k];if(y>m)y=1;if(y<1)y=m;                    int u=num[i][j];                    int v=num[x][y]+n*m;                    if(str[j]==ch[k])                        addedge(u,v,1,0);                    else                        addedge(u,v,1,1);            }        }    }    S=0;T=n*m*2+1;    for(int i=1;i<=n*m;i++){        addedge(S,i,1,0);        addedge(i+n*m,T,1,0);    }    cout<<mcf()<<endl;}

T3单词

暴力KMP就能过

#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<algorithm>using namespace std;char str[205][100005];int id[205],len[205],ans[205];int pre[100005];int n;bool cmp(int a,int b){    return len[a]<len[b];}int main(){    scanf("%d",&n);#define str str[i]#define len len[i]    for(int i=1;i<=n;i++){        scanf("%s",str+1);str[0]='$';        len=strlen(str+1);    }#undef str#undef len#define str1 str[i]#define str2 str[j]#define len1 len[i]#define len2 len[j]#define ans ans[i]    for(int i=1;i<=n;i++){        memset(pre,0,sizeof(pre));        for(int fix=0,k=2;k<=len1;k++){            while(fix && str1[fix+1]!=str1[k])fix=pre[fix];            if(str1[fix+1]==str1[k])fix++;            pre[k]=fix;        }        ans=0;        for(int j=1;j<=n;j++){            if(len2<len1)continue;            for(int fix=0,k=1;k<=len2;k++){                while(fix && str1[fix+1]!=str2[k])fix=pre[fix];                if(str1[fix+1]==str2[k])fix++;                if(fix==len[i])ans++,fix=pre[fix];            }        }       }    for(int i=1;i<=n;i++)cout<<ans<<endl;#undef ans#undef str1#undef str2#undef len1#undef len2}
0 0
原创粉丝点击