025.抽象打表

小红写谱

nowcode

先看抽象打表做法

  • 首先注意到重复的按键可以忽略,只要把它们连着排贡献就都是0
    这样就变成了一个长度最大为 8 的数组

  • 对于 1 ~ 8 的所有组合 :2^8
    去掉空集就是 2^8 - 1

  • 对一个长度为 n 的组合它的所有排列数 : n !

  • 总代价为

\[\sum_{i=1}^{8}i *i! \]

  • 数量级为 1e6

  • 建立映射,常数处理询问

code

实现:

递归枚举组合,嵌套递归枚举排列

对组合建立映射 1 2 3 5 8 的key值为12358


#include<bits/stdc++.h>
using namespace std;
vector<int>ans(12345679);
int sum;
vector<int>p;
vector<int>a;
bitset<10>vis;
void dfs(){
    if(p.size()==a.size()){
        int t=0;
        for(int i=1;i<(int)p.size();++i){
            t+=min(abs(p[i]-p[i-1]),8-abs(p[i]-p[i-1]));
        }
        sum=min(sum,t);
        return;
    }
    for(int i=0;i<(int)a.size();++i){
        if(vis[i])continue;
        vis[i]=1;
        p.push_back(a[i]);
        dfs();
        p.pop_back();
        vis[i]=0;
    }
}
void dfs1(int x,int key){
    if(x>8){
        if(a.empty())return;//去掉空集
        sum=INT_MAX;
        p.clear();
        vis.reset();
        dfs();
        ans[key]=sum;
        return;
    }
    dfs1(x+1,key);
        a.push_back(x);
        dfs1(x+1,key*10+x);
        a.pop_back();
}
int main(){
    dfs1(1,0);
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        vector<int>cnt(9);
        while(n--){
            int t;cin>>t;
            cnt[t]++;
        }
        int key=0;
        for(int i=1;i<=8;++i){
            if(cnt[i]){
                key=key*10+i;
            }
        }
        cout<<ans[key]<<'\n';
    }
}

正解

  • 首先还是重复的按键没有贡献

  • 顺时针/逆时针转一圈代价最小

  • 所以 :首尾连成一个环、枚举起点转一圈即可

其实这等价为转一整圈的代价(8)- 距离最远的两个键的距离

这不就是题目的情境吗 !!

舞萌!

#include<bits/stdc++.h>
using namespace std;
int main(){
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        vector<int>cnt(9);
        for(int i=0;i<n;++i){
            int a;
            cin>>a;
            cnt[a]++;
        }
        vector<int>a;
        for(int i=1;i<=8;++i){
            if(cnt[i]){
                a.push_back(i);
            }
        }
        int m=0,p=a.back()-8;
        for(int x:a){
            m=max(m,x-p);
            p=x;
        }
        cout<<8-m<<'\n';
    }
}
posted @ 2025-12-26 22:10  射杀百头  阅读(3)  评论(0)    收藏  举报