HGOI7.24集训题解

题解

今天大概是没带脑子…本来以为今天的题起码可以打230,但实际得分只有170…..orz。15年的题其实觉得还行。


第一题——神奇的幻方(magic)

【题目描述】

  • 给出整数n按照规则求出矩阵。
  • 规则:

    • 首先将1写在第一行的中间。之后,按如下方式从小到大依次填写每个数

    • 1.若 k 1 在第一行但不在最后一列,则将 k 填在最后一行, k 1 所在列的右一列;

    • 2.若在最后一列但不在第一行,则将 k 填第一列, k 1 所在行的上一行;

    • 3.若 k 1 在第一行最后一列,则将 k 1 的正下方;

    • 4.若 k 1 既不在第一行,也不在最后一列,如果 k 1 的右上方还未填数,则将 k 填在 k 1 的右上方,否则将 k 填在 k 1 的正下方。


  • 真的是一个无脑的简单模拟题….但首测只拿了70分…因为数组越界orz
  • 详见代码。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
void fff(){
    freopen("magic.in","r",stdin);
    freopen("magic.out","w",stdout);
}
int map[1000][1000];
int l[1700],r[1700];
int nn;

int main(){
    fff();
    cin>>nn;
    map[1][(nn+1)/2]=1;
    l[1]=1;
    r[1]=(nn+1)/2;
    for (int i=2;i<=nn*nn;i++){
        if(l[i-1]==1&&r[i-1]!=nn){
            map[nn][r[i-1]+1]=i;
            l[i]=nn;
            r[i]=r[i-1]+1;
        }else if(l[i-1]!=1&&r[i-1]==nn){
            map[l[i-1]-1][1]=i;
            l[i]=l[i-1]-1;
            r[i]=1;
        }else if(l[i-1]==1&&r[i-1]==nn){
            map[l[i-1]+1][r[i-1]]=i;
            l[i]=l[i-1]+1;
            r[i]=r[i-1];
        }else if(l[i-1]!=1&&r[i-1]!=nn){
            if(!map[l[i-1]-1][r[i-1]+1]){
                map[l[i-1]-1][r[i-1]+1]=i;
                l[i]=l[i-1]-1;
                r[i]=r[i-1]+1;
            }else{
                map[l[i-1]+1][r[i-1]]=i;
                l[i]=l[i-1]+1;
                r[i]=r[i-1];
            }
        }
    }

    for (int i=1;i<=nn;i++){
        for (int j=1;j<=nn;j++){
            printf("%d ",map[i][j]);
        }
        printf("\n");
    }
    return 0;
}

第二题——信息传递(message)

【题目描述】

  • 给出n个点n条有向边,求图中最小强联通分量的点数。

  • 因为n个点n条边。所以如果全联通的话,就只存在1个环,拿来一把dfs或者tarjan算法。就可以求出大小了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
void fff(){
    freopen("message.in","r",stdin);
    freopen("message.out","w",stdout);
}
const int MAXN=200010;
int s[MAXN],t=0;
int n;
int a[MAXN];
int low[MAXN],dfn[MAXN],t_lorck=0,ans=MAXN*10;
void tarjan(int u){
    low[u]=dfn[u]=++t_lorck;
    if(!dfn[a[u]]){
        s[++t]=a[u];
        tarjan(a[u]);

        low[u]=min(low[u],low[a[u]]);
    }else{
        low[u]=min(low[u],dfn[a[u]]);
    }
    if(low[u]==dfn[u]){
        int sum=1;
        while (s[t]!=u){
            sum++;
            t--;
        }
        if(sum>2) ans=min(ans,sum);
    }
}
int main(){
    fff();
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++){
        if(!dfn[i]){
            s[++t]=i;
            tarjan(i);
        }
    }
    cout<<ans;
    return 0;
}

第三题——斗地主(landlords)

【题目描述】

  • 如题吧,给出T组数据,每组n张牌,问最快几步打完所有牌。
  • 规则见图。

这里写图片描述

扫描二维码关注公众号,回复: 2819760 查看本文章

  • 其实这道题的数据在前三十分是比较水的。本来无脑可以拿三十分的。
  • 但是我觉得还是打把dfs才对得起自己的良心。然后——超时了orz
  • 其实也不算很烦这道题,思路比较好想:首先能够出顺子就出顺子,能够双排或者带掉就带掉,符合贪心的原则。但是由于可能出现两幅顺子重叠的情况:3 4 5 5 6 6 7 7 8 9 。所以就需要加上的dfs来进行更优的选择了。
  • 代码不多,就200行orz
  • 每次dfs之后都统计剩下的牌所能尽量打出的次数。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
void fff(){
    freopen("landlords.in","r",stdin);
    freopen("landlords.out","w",stdout);
}
int T,n;
int a[30],ans;
int sanpai(){
    int cnt[5],temp[14],ret=0;
    for (int i=1;i<=14;i++) cnt[a[i]]++;
    for (int i=1;i<=14;i++) temp[i]=a[i];
    if(cnt[4]&&(cnt[2]>2||cnt[3]>2)){//4-2
        for (int i=1;i<=14;i++){
            if(temp[i]==4){
                for (int j=1;j<=14;j++){
                    if(j==i||temp[j]!=2) continue;
                    if(temp[i]<4) break;
                    for (int k=1;k<=14;k++){
                        if(k==i||k==j) continue;
                        if(temp[k]==2){
                            temp[i]-=4;
                            temp[j]-=2;
                            temp[k]-=2;
                            cnt[4]--;
                            ret++;
                            break;
                        }
                    }
                }
            }
        }
    }
    if(cnt[4]&&(cnt[2]||cnt[3]||cnt[1])){
        for (int i=1;i<=14;i++){
            if(temp[i]==4){
                for (int j=1;j<=14;j++){
                    if(i==j||temp[j]!=1) continue;
                    if(temp[i]!=4) break;
                    for (int k=1;k<=14;k++){
                        if(k==i||k==j) continue;
                        if(temp[k]==1){
                            temp[i]-=4;
                            temp[j]--;
                            temp[k]--;
                            cnt[4]--;
                            ret++;
                            break;
                        }
                    }
                }
            }
        }
    }
    if(cnt[4]&&(cnt[2]||cnt[3])){
        for (int i=1;i<=14;i++){
            if(temp[i]==4){
                for (int j=1;j<=14;j++){
                    if(j==i) continue;
                    if(temp[j]==2){
                        temp[i]-=4;
                        ret++;
                        temp[j]-=2;
                        cnt[4]--;
                    }
                }
            }
        }
    }
    for (int i=1;i<=14;i++){
        if(temp[i]>=3){
            for (int j=1;j<=14;j++){
                if(temp[j]==2){
                    temp[i]-=3;
                    temp[j]-=2;
                    ret++;
                    break;
                }
                if(temp[j]==1){
                    temp[i]-=3;
                    temp[j]-=1;
                    ret++;
                    break;
                }
            }
        }
    }
    for (int i=1;i<=14;i++){
        if(temp[i]==4) temp[i]-=4,ret++;
        else if(temp[i]==3) temp[i]-=3,ret++;
        else if(temp[i]==2) temp[i]-=2,ret++;
        else if(temp[i])temp[i]-=1,ret++;
    }
    return ret;
}
void dfs(int step){
    if(step>=ans){
        return;
    }
    for (int i=1;i<=14;i++){
        if(a[i]) break;
        if(i==14) {
            ans=step;
            return;
        }
    }
    int temp=sanpai();
    if(temp+step<ans) ans=step+temp;
    int cnt[5];
    memset(cnt,0,sizeof(cnt));
    for (int i=1;i<=14;i++) cnt[a[i]]++;
    if(cnt[3]>=3){
        for (int i=1;i<=10;i++){
            for (int l=2;l<=12;l++){
                for (int p=i;p<=l+i;p++){
                    if(a[p]<3||p>12) break;
                    else{
                        if(p==l+i){
                            for (int q=i;q<=p;q++) a[q]-=3;
                            cnt[3]-=(l+1);
                            dfs(step+1);
                            cnt[3]+=(l+1);
                            for (int q=i;q<=p;q++) a[q]+=3;
                        }
                    }
                }
            }
        }
    }
    if(cnt[2]>=3){
        for (int i=1;i<=10;i++){
            for (int l=2;l<=12;l++){
                for (int p=i;p<=l+i;p++){
                    if(a[p]<2||p>12) break;
                    else{
                        if(p==l+i){
                            for (int q=i;q<=p;q++) a[q]-=2;
                            cnt[2]-=(l+1);
                            dfs(step+1);
                            cnt[2]+=(l+1);
                            for (int q=i;q<=p;q++) a[q]+=2;
                        }
                    }
                }
            }
        }
    }
    if(cnt[1]+cnt[2]+cnt[3]>5){
        for (int i=1;i<=10;i++){
            for (int l=4;l<=12;l++){
                for (int p=i;p<=p+l;p++){
                    if(!a[p]||p>12) break;
                    else{
                        if(p==l+i){
                            for (int q=i;q<=p;q++) a[q]--;
                            dfs(step+1);
                            for (int q=i;q<=p;q++) a[q]++;
                        }
                    }

                }
            }
        }
    }
}
void init(){
    memset(a,0,sizeof(a));
}
int main(){
    fff();
    scanf("%d%d",&T,&n);
    while (T--){
        init();
        for (int i=1;i<=n;i++){
            int t,s;
            scanf("%d%d",&t,&s);
            if(t>=3&&t<=13) a[t-2]++;
            if(t==0) a[14]++;
            if(t==1) a[12]++;
            if(t==2) a[13]++;
        }
        ans=n;
        dfs(0);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42037034/article/details/81185365
今日推荐