2017.10.26离线赛总结

来源:互联网 发布:三和软件 编辑:程序博客网 时间:2024/06/05 04:46

magic ——4124

思路:强模拟,不解释…

message ——4125

思路:仔细读完题,实际上是找一个最小的环,那么便bfs,但这样只有60,
因为n<=200 000,也便知道只有O(n log n)的复杂度,而且,此题的关系比较明显——父子关系,脑海一闪而过——并查集,再思考一下,并两个集合,查一数,十分符合。

#include<bits/stdc++.h>#define REP(i,f,t ) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t ) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define LL long long#define INF 0x3f3f3f3f#define N 200005using namespace std;int n;vector<int>E[N];bool vis[N];struct p100{    int ans;    int D[N],fa[N],nxt[N];    int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}    void merege(int x,int y){        int fx=Find(x);        int fy=Find(y);        fa[fx]=fy;    }    void dfs(int x,int dep){        vis[x]=1;        D[x]=dep;        if(!vis[nxt[x]])dfs(nxt[x],dep+1);        else {            int sum=D[x]-D[nxt[x]]+1;            ans=min(ans,sum);        }    }    void solve(){        ans=INF;        REP(i,1,n)fa[i]=i;        REP(i,1,n){            int x;scanf("%d",&x);nxt[i]=x;            if(Find(x)!=Find(i))merege(i,x);            else {                memset(vis,0,sizeof(vis));                dfs(i,0);            }        }        cout<<ans<<endl;    }}p100;int main(){//  freopen("message.in","r",stdin);//  freopen("message.out","w",stdout);    cin>>n;    p100.solve();}

landlords ——4126

思路:爆搜…(还是要考虑周到,再敲代码),也就这么几种特殊情况:单顺子,双顺子,三顺子,三带一或二,四不带,四带二单或一对。而这看起来挺多,但再次分类一下,单顺,双顺,三顺,三带,四带。

#include<bits/stdc++.h>#define REP(i,f,t ) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t ) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define LL long long#define INF 0x3f3f3f3f#define N 30using namespace std;int T,n,x,y,ans;int mark[N];void Init(){    memset(mark,0,sizeof(mark));    ans=0;}bool check(){    REP(i,1,15)        if (mark[i]) return 0;    return 1;}void dfs(int cnt){    if(cnt>ans)return;    if (check()) {        ans=min(ans,cnt);        return;    }    int sum=0;    REP(i,1,13)if(mark[i])sum++;    if(mark[14]+mark[15])sum++;    ans=min(ans,cnt+sum);    REP(l,1,5){        if (l==1){// single shunzi            REP(i,1,8)                if (mark[i]) {                    bool flag=1;                    for (int j=i+1; j<=i+3; ++j)                        if (!mark[j]) {                            flag=0;                            break;                        }                    if (!flag) continue;                    for (int j=i+4; j<13&&mark[j]; ++j) {                        for (int k=i; k<=j; ++k) --mark[k];                        dfs(cnt+1);                        for (int k=i; k<=j; ++k) ++mark[k];                    }                }        }        if (l==2) {//double shunzi            REP(i,1,10)                if (mark[i]>=2&&mark[i+1]>=2)                    for (int j=i+2; j<13&&mark[j]>=2; ++j) {                        for (int k=i; k<=j; ++k) mark[k]-=2;                        dfs(cnt+1);                        for (int k=i; k<=j; ++k) mark[k]+=2;                    }        }        if (l==3) {//triple shunzi            REP(i,1,11)                if (mark[i]>=3) {                    if (mark[i+1]<3) continue;                    for (int j=i; j<13&&mark[j]>=3; ++j) {                        for (int k=i; k<=j; ++k) mark[k]-=3;                        dfs(cnt+1);                        for (int k=i; k<=j; ++k) mark[k]+=3;                    }                }        }        if (l==4) {//san dai            REP(i,1,13)                if (mark[i]>=3) {                    mark[i]-=3;                    REP(j,1,15)                        if (mark[j]) {                            --mark[j];                            dfs(cnt+1);                            ++mark[j];                        }                    REP(j,1,15)                        if (mark[j]>=2) {                            mark[j]-=2;                            dfs(cnt+1);                            mark[j]+=2;                        }                    mark[i]+=3;                }        }        if (l==5) {//si dai            REP(i,1,15)                if (mark[i]>=4) {                    mark[i]-=4;                    REP(j,1,15)                        if (mark[j]) {                            --mark[j];                            REP(k,j,15)                                if (mark[k]) {                                    --mark[k];                                    dfs(cnt+1);                                    ++mark[k];                                }                            ++mark[j];                        }                    mark[i]+=4;                }            REP(i,1,15)                if (mark[i]>=4) {                    mark[i]-=4;                    REP(j,1,15)                        if (mark[j]>=2) {                            mark[j]-=2;                            REP(k,j,15)                                if (mark[k]>=2) {                                    mark[k]-=2;                                    dfs(cnt+1);                                    mark[k]+=2;                                }                            mark[j]+=2;                        }                    mark[i]+=4;                }        }    }}int main() {    scanf("%d%d",&T,&n);    while (T--){        Init();        REP(i,1,n){            scanf("%d%d",&x,&y);            if (!x) mark[y+13]++;            if (x==1||x==2) mark[x+11]++;            if (x>=3) mark[x-2]++;        }        REP(i,1,13)if(mark[i])ans++;        if(mark[14]+mark[15])ans++;        dfs(0);        printf("%d\n",ans);    }}

小结:今天的最后一题还是敲地太乱了,没怎么想好久开始敲,结果连爆搜都敲不出来——深思熟虑后再动键盘…

原创粉丝点击