csust组队练习赛第二场A题:Yard(状态压缩)

今天做了下csust的一场比赛,这是A题,先是枚举每一行超时了一次,之后又wa了数次。。。最后还是艰难的ac了。。。同一道题,1A和10A会得到两种完全不同的喜悦感!

题目:小oy是一位文艺青年,他园艺精湛,在自家后院里种满了美丽的线段树。他家后院是一个由n*m个方格组成的矩阵,有些方格上种有线段树。小oy认为:若每个格子的相邻四格(上下左右)的线段树加起来都恰好是偶数棵,那么后院就是美观的。小oy拔掉或新建一棵线段树都需要消耗1点体力,现在他想知道让后院变得美观最少需要消耗多少体力值。

(四角落位置只有两格相邻,边界非角落位置只有三格相邻)

输入:第一行两个正整数n,m。(n<=10, m<=100)接下来n行,每行一个长m的字符串,代表该行的初始状态。(#表示线段树,-表示空地)

输出:最小消耗体力值

Sample Input :

2 4

#-#-

-#--

Sample output:

3

用状态压缩+枚举。状态压缩:用一个数组A表示原矩阵,有线段树的地方置为1,空地置为0。但需要注意的是本题n和m的范围!n<=10 , m<=100,如果枚举每一行的状态,那时间复杂度为O(2^m *n^2) ,肯定超时,所以应该枚举每一列!在输入的时候将行与列转换一下,时间复杂度为O(2^n*m^2),完全可以接受。。。具体方法是:枚举每个第一列,然后依题意确定每个下一列(对于b[r-1][c],已知sum = b[r-2][c]+b[r-1][c-1]+b[r-1][c+1],则当且仅当b[r][c]=sum%2时点(r-1, c)才能满足题意),不过要注意最后一列需要单独判断,因为这个wa了好多次。。。

#include<algorithm>
#include<iostream>
using namespace std;

const int maxn = 111;
const int INF = 1e9;
int A[maxn][maxn], b[maxn][maxn], n, m;

int check(int s)
{
    memset(b, 0, sizeof(b));
    for(int c=0; c<n; c++) // 枚举排列
    {
        if(s & (1<<c)) b[0][c] = 1;
    }
    for(int r=1; r<m; r++)
        for(int c=0; c<n; c++)
        {
            int sum = 0; //sum为b[r-1][c]的上 左 右 三个之和
            if(r > 1) sum += b[r-2][c];
            if(c > 0)  sum+= b[r-1][c-1];
            if(c < n-1) sum+= b[r-1][c+1];
            b[r][c] = sum%2;    //由sum确定b[r][c] 使b[r-1][c]满足题意
        }
    for(int i=0; i<n; i++) //单独判断最后一列是否满足
    {
        int sum = 0;
        if(i > 0)   sum+=b[m-1][i-1];
        if(i < n-1) sum+=b[m-1][i+1];
        if(m > 1)   sum+=b[m-2][i];
        if(sum%2)   return INF;
    }
    int cnt = 0;
    for(int r=0; r<m; r++)
        for(int c=0; c<n; c++)
            if(A[r][c] != b[r][c]) cnt++;//求体力值
    return cnt;
}

int main()
{
    char ch[maxn];
    while(cin >> n >> m)
    {
        int sum = 0;
        for(int i=0; i<n; i++)
        {
            cin>>ch;
            for(int j=0; j<m; j++)
            {
                if(ch[j] == '#')
                {
                    A[j][i] = 1;//行与列转换
                    sum++;
                }
                else
                {
                    A[j][i] = 0;
                }
            }
        }
        int ans = INF;
        for(int s=0; s<(1<<n); s++) // 枚举所有列
        {
            ans = min(ans, check(s));
        }
        if(ans == INF) ans = sum; //若无解 则删除所有‘#’
        cout<<ans<<endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Tool chain是指一系列的工具和软件集合,用于开发、编译和调试特定平台或体系结构的软件。每个平台或体系结构都有自己的工具链,用于将源代码转换为可执行文件。这些工具通常包括编译器、汇编器、链接器等,用于将高级语言代码转换为机器语言代码,并将多个目标文件链接为一个可执行文件。 例如,在RISC-V架构中,可以使用RISC-V GNU Toolchain来构建开发环境。该工具链基于GNU binutils和gcc,提供了汇编器、反汇编器、链接器、归档器和C编译器等工具。要搭建RISC-V GNU Toolchain,可以使用命令"git clone https://github.com/riscv/riscv-gnu-toolchain"将工具链的源代码克隆到本地,并通过"git submodule update --init --recursive"命令更新并初始化子模块。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [RISCV toolchain编译工具链搭建](https://blog.csdn.net/csust_sq/article/details/118787936)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Motorola DSP56800 Tool Chain-开源](https://download.csdn.net/download/weixin_42100032/17544806)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值