zoukankan      html  css  js  c++  java
  • 【dp每日一题】CF543C. Remembering Strings

    大意:

    给出n个字符串,每个字符串的长度均为m,以及一个矩阵,代表修改每个字符串上每个值所需要的花费,现在要求每个字符串至少有一个位置上的值是和别的所有字符串都不一样的,问最少的花费((1 leq n,mleq 20)

    思路:

    由于n很小,可以想到状压dp,定义dp[state]为当前状态下的最少花费,“状态”代表有哪些字符串已经符合要求,例如101代表第1个和第3个字符串已经是有某一位独一无二了,那么最后的结果就是dp[1<<n-1]。

    至于怎么转移,我们可以发现,因为n很小,小于26,所以可以随意修改字符,而不需要担心是否修改后和别的字符串重复,那么对于某一个字符串没有达到条件,我们有两种方法可以进行修改:

    第一种:选择某1位,修改这个字符串的这一位。

    第二种:选择某一位,将和这一位相同的其他字符串全部修改为独一无二的值,这样还需要维护一个数组,代表修改与第i个字符串的第k个位置相同的其他字符串,需要多少花费。

    需要注意的是,应该是在state从小到大的同时,j也从小到大遍历,保证传递性

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int n, m,c[25][25],sumc[25][25],state[25][25],dp[1<<25];
    string s[25];
    int main(){
        cin >> n >> m;
        for (int i = 0; i < n;i++){
            cin >> s[i];
        }
        for (int i = 0; i < n;i++){
            for (int j = 0; j < m;j++){
                cin >> c[i][j];
            }
        }
        for (int i = 0; i < n;i++){
            for (int k = 0; k < m;k++){
                int maxn = 0;  //记录相同的元素里面修改需要最大的值,留着不改
                for (int j = 0; j < n;j++){
                    if(s[i][k]!=s[j][k]){
                        continue;
                    }
                    sumc[i][k] += c[j][k];
                    maxn = max(c[j][k], maxn);
                    state[i][k] |= (1 << j);
                }
                sumc[i][k] -= maxn;
            }    
        }
        int T = (1 << n) - 1;
        for (int i = 0; i <= T;i++){
            dp[i] = 0x3f3f3f3f;
        }
        dp[0] = 0;
        for (int i = 0; i < T;i++){
            for (int j = 0; j < n;j++){
                if((i&(1<<j))==0){      //每次优先更新最前面的,保证传递性
                    int a = 1 << j;
                    for (int k = 0; k < m;k++){
                        int b = state[j][k];
                        dp[i | a] = min(dp[i | a], dp[i] + c[j][k]);
                        dp[i | b] = min(dp[i | b], dp[i] + sumc[j][k]);
                    }
                    break;
                }
            }
        }
        cout << dp[T] << endl;
        return 0;
    }
    
  • 相关阅读:
    30行代码实现微信自动回复机器人
    用Python来P图
    部署Scrapy分布式爬虫项目
    为什么自学Python看不进去?0基础入门Python有哪些捷径?
    学Python Web开发框架到什么程度可以找到开发的工作?
    Python不能帮你找到女朋友,却能让你成为有钱的单身狗
    SQL 的基本使用概念简介
    Python 面向对象编程的一些知识点总结
    一 数据的概括性度量
    三 k-近邻算法(k-Nearest Neighbors KNN)
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14077413.html
Copyright © 2011-2022 走看看