BZOJ3170~3172 TJOI2013 DAY1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Elemmir/article/details/51122975

T1松鼠聚会

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

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
#define LL long long
const 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
}
阅读更多
换一批

没有更多推荐了,返回首页