0
点赞
收藏
分享

微信扫一扫

机器学习2--逻辑回归(案列)

小禹说财 2024-02-16 阅读 8

原题链接:https://ac.nowcoder.com/acm/contest/75174/F

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

小红拿到了一个字符矩阵,矩阵中仅包含"red"这三种字符。

小红每次操作可以将任意字符修改为"red"这三种字符中的一种。她希望最终任意两个相邻的字母都不相同。小红想知道,至少需要修改多少个字符?

输入描述:

第一行输入两个正整数n,m,代表矩阵的行数和列数。
接下来的n行,每行输入一个长度为m的、仅由"red"这三种字符组成的字符串。
1≤n≤4
1≤m≤1000

输出描述:

一个整数,代表需要修改的字母数量的最小值。

示例1

输入

2 3
ree
dee

输出

2

说明

修改为:
red
dre
即可。

解题思路:

cpp代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N=6,M=1010;
int n,m;
char gg[N][M];
int g[N][M];    //映射数组,将原来的red映射为012
vector<int>state;  //存储所有合法状态
vector<int>arrive[100]; //存储每个合法状态的所有合法转移
int p3[5]={1,3,9,27,81}; //存储3的幂
int f[M][100]; //f[i][j]表示处理完前i行,并且第i行状态为j的最少修改次数

bool check(int x)  //检查当前状态x是否合法,合法指的是x的三进制表示所有相邻位都不相同
{
    int last=-1,cnt=n;
    while(cnt--){
        int v=x%3;
        if(v==last)return false;
        x/=3;
        last=v;
    }
    return true;
}

bool check(int x,int y) //判断俩个数的三进制表示是否所有位都不同,
{
    for(int i=0;i<n;i++){
        if(x%3==y%3)return false;
        x/=3,y/=3;
    }
    return true;
}
int a1[4]={};
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)scanf("%s",gg[i]);
    for(int i=0;i<n;i++)//先把red映射为012
        for(int j=0;j<m;j++)
            if(gg[i][j]=='r')g[i][j]=0;
            else if(gg[i][j]=='e')g[i][j]=1;
            else g[i][j]=2;
    for(int i=0;i<p3[n];i++) //首先预处理所有合法状态
    {
        if(check(i))state.push_back(i);
    }
    
    for(int i=0;i<state.size();i++){ //预处理每个合法状态的所有合法转移
        
        for(int j=0;j<state.size();j++)
        {
            //当俩行三进制表示每个位都不同时,才能转移
            if(check(state[i],state[j]))arrive[i].push_back(j);
        }
    }
    memset(f,0x3f,sizeof f);
    for(int i=0;i<m;i++)
    {
        for(int a=0;a<state.size();a++){
            for(int j=0;j<n;j++)a1[j]=0;  //记得a1数组要初始化,不初始化可能会受到前面的影响
            int x=state[a],v1=0,cnt1=0;
            while(x){
                a1[cnt1++]=x%3;
                x/=3;
            }
            for(int j=0;j<n;j++)
                if(g[j][i]!=a1[j])v1++; //计算当前位置变为状态state[a]需要修改多少次
            if(i==0){
                f[i][a]=v1; //第一行前面没有行,所以特殊处理,
                continue;
            }
            for(auto b:arrive[a]){  //前面预处理好了所有合法转移,所以这里直接计算即可
                f[i][a]=min(f[i][a],f[i-1][b]+v1);
            }
        }
    }
    int ans=0x3f3f3f3f;
    //计算答案,非法状态会是一个非常大的值,所以这里我们直接枚举所有状态也不影响答案
    for(int j=0;j<p3[n];j++)
        ans=min(ans,f[m-1][j]);
    cout<<ans<<endl;
    return 0;
}
举报

相关推荐

0 条评论