P3087 [USACO13NOV]Farmer John has no Large Brown Cow S(进制)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3087 [USACO13NOV]Farmer John has no Large Brown Cow S(进制)相关的知识,希望对你有一定的参考价值。

P3087 [USACO13NOV]Farmer John has no Large Brown Cow S(进制)

就是进制转换。

先预处理每种形容词的个数,排序。

然后求出 n n n个牛当前的排名。

然后对这 n n n头牛排序。

更新实际的 k k k

然后再倒着从左往右求出每个进制位上的数字即可。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n, k;
int adj_num = 0;
vector<string> str[105];          //str[i]表示用于修饰第i头牛的形容词
vector<string> adj_by_pos[35];    //adj_by_pos[i]表示所有在位置i出现的形容词
set<string> is_appear[35];        //is_appear[i]用于判断在位置i上,某个形容词是否出现
int weight_in_pos[35];            //每一位代表的值(按照字典序排在第几)
map<string, int> rank_in_pos[35]; //rank_in_pos[i][j]代表在位置i上,字符串j按照字典序排序,排在第几
int cow_rank[105];                //fj没有的牛的排名
bool debug = false;               //调试开关,可以打开去体会一下解题的过程
void mapping()                    //对每类形容词进行字典序排序,把结果存在 rank[i][j]中,其中 i 代表形容词类型,j 代表排名
                                 //注意这里的排名从0开始(这是把单词映射到数字上,数字是从0开始的)
    for (int i = 1; i <= adj_num; i++)
    
        int rank = 0;
        for (auto j : adj_by_pos[i]) //c++11的新特性,意思是用j遍历所有adj_by_pos[i]的元素
        
            rank_in_pos[i][j] = rank;
           // if (debug)
           //     cout << j << " rank = " << rank << " i = " << i << endl;//
            rank++;
        
    


int get_pos(int cow_id)

    int ans = 0;
    for (int i = 1; i <= adj_num; i++)
    
        ans += weight_in_pos[i] * (rank_in_pos[i][str[cow_id][i - 1]]);
    
    return ans + 1; //答案可能是0,但是排位应该从1开始


int main()

    ios::sync_with_stdio(false);
    cin >> n >> k;
    string temp_str;
    for (int i = 1; i <= n; i++)
    
        cin >> temp_str;
        while (temp_str != "no")
        
            cin >> temp_str;
        
        int adj_pos = 1;

        while (1)
        
            cin >> temp_str;
            if (temp_str == "cow.")
            
                break;
            
            str[i].push_back(temp_str);
            if (!is_appear[adj_pos].count(temp_str)) //还没有出现过,这里是去重操作
            
                adj_by_pos[adj_pos].push_back(temp_str);
                is_appear[adj_pos].insert(temp_str);
            
            if (i == 1)
            
                adj_num++; //计算形容词的种类数
            
            adj_pos++;
        
    
    for (int i = 1; i <= adj_num; i++)
    
        sort(adj_by_pos[i].begin(), adj_by_pos[i].end()); //对每个类型的形容词进行排序
    

    weight_in_pos[adj_num + 1] = 1;            //第一位代表的数字应该是1
    adj_by_pos[adj_num + 1].push_back("temp"); //1和1相乘是1,所以要push一个元素进去,这样子size就是1

    for (int i = adj_num; i >= 1; i--) //计算每一位在十进制中代表的值(这里的位的计算方法和平时的方法是反的)
                                      //这是因为本题中的形容词类型和数字系统的 “位” 是相反的
       // if (debug)
         //   cout << "i" << i << endl;
        weight_in_pos[i] = weight_in_pos[i + 1] * adj_by_pos[i + 1].size();
    
    mapping();
    for (int i = 1; i <= n; i++)
    
        cow_rank[i] = get_pos(i); //计算出要删除的n头牛的整体排名
      //  if (debug)
         //   cout << "cowrkw " << i << " = " << cow_rank[i] << endl;
    
    sort(cow_rank + 1, cow_rank + n + 1); //按照每种牛的排名进行排序
    for (int i = 1; i <= n; i++)
    
        if (cow_rank[i] <= k)
        
            k++;
        
        else
        
            break;
        
    
    k--; //k原本代表的是排在第几的牛,但是我们已经把牛的排名转化成数字了,
        //排名最小的牛的数字是0而不是1,所以这里要减1
   // if (debug)
    //    cout << "new k" << k << endl;
    for (int i = 1; i <= adj_num; i++)
    
        cout << adj_by_pos[i][(k) / weight_in_pos[i]] << " ";
       // if (debug)
        //    cout << "i " << i << " (k) / weight_in_pos[i] " << (k) / weight_in_pos[i] << endl;
        k %= weight_in_pos[i];
    
   return 0;

以上是关于P3087 [USACO13NOV]Farmer John has no Large Brown Cow S(进制)的主要内容,如果未能解决你的问题,请参考以下文章

[USACO 13NOV]No Change

[luogu] P3089 [USACO13NOV]POGO的牛Pogo-Cow

[USACO13NOV]没有找零No Change [TPLY]

3312. [USACO13NOV]No Change状压DP

[USACO13NOV]Crowded Cows

[USACO13NOV]空荡荡的摊位Empty Stalls