暑期实践日志(四)

Painter‘s Problem

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 4912   Accepted: 2385

Description

There is a square wall which is made of n*n small square bricks. Some bricks are white while some bricks are yellow. Bob is a painter and he wants to paint all the bricks yellow. But there is something wrong with Bob‘s brush. Once he uses this brush to paint brick (i, j), the bricks at (i, j), (i-1, j), (i+1, j), (i, j-1) and (i, j+1) all change their color. Your task is to find the minimum number of bricks Bob should paint in order to make all the bricks yellow. 

Input

The first line contains a single integer t (1 <= t <= 20) that indicates the number of test cases. Then follow the t cases. Each test case begins with a line contains an integer n (1 <= n <= 15), representing the size of wall. The next n lines represent the original wall. Each line contains n characters. The j-th character of the i-th line figures out the color of brick at position (i, j). We use a ‘w‘ to express a white brick while a ‘y‘ to express a yellow brick.

Output

For each case, output a line contains the minimum number of bricks Bob should paint. If Bob can‘t paint all the bricks yellow, print ‘inf‘.

Sample Input

2
3
yyy
yyy
yyy
5
wwwww
wwwww
wwwww
wwwww
wwwww

Sample Output

0
15这道题目也是高斯消元法的经典题目,但是和之前的题目想比有些不同。之前的开关问题在经过高斯消元后,只需要统计其中自有变量的个数,在进行移位运算即可;在这道题中,需要解决的是在高斯消元后,若只有唯一解则,统计变化的旗子个数,若有多个解即有自由变量那么要枚举自由变量的所有可能,取最小值。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=300;
int a[maxn][maxn];
int x[maxn];
int free_x[maxn];
int free_num;
int equ,var;
int gauss()
{
    int i,j,k,col,max_r;
    free_num=0;
    for(k=0,col=0;k<equ&&col<var;k++,col++)
    {
        max_r=k;
        for(int i=k+1;i<equ;i++)
        {
            if(abs(a[i][col])>abs(a[max_r][col]))
                max_r=i;
        }
        if(a[max_r][col]==0)
        {
            k--;
            free_x[free_num++]=col;
            continue;
        }
        if(max_r!=k)
        {
            for(int j=col;j<var+1;j++)
                swap(a[k][j],a[max_r][j]);
        }
        for(int i=k+1;i<equ;i++)
        {
            if(a[i][col]!=0)
            {
                for(int j=col;j<var+1;j++)
                    a[i][j]^=a[k][j];
            }
        }
    }
    for(int i=k;i<equ;i++)
    {
        if(a[i][col]!=0)
            return -1;
    }
    if(k<var)
        return var-k;
    for(int i=var-1;i>=0;i--)
    {
        x[i]=a[i][var];
        for(int j=i+1;j<var;j++)
            x[i]^=(a[i][j]&&x[j]);
    }
    return 0;
}
void init(int r)
{
    memset(a,0,sizeof(a));
    memset(x,0,sizeof(x));
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<r;j++)
        {
            int t=i*r+j;
            a[t][t]=1;
            if(i>0)
                a[(i-1)*r+j][t]=1;
            if(i<r-1)
                a[(i+1)*r+j][t]=1;
            if(j>0)
                a[i*r+j-1][t]=1;
            if(j<r-1)
                a[i*r+j+1][t]=1;
        }
    }
}
void solve()
{
    int f=gauss();
    if(f==-1)
    {
        printf("inf\n");
        return;
    }
    else if(f==0)
    {
        int ans=0;
        for(int i=0;i<equ;i++)
            ans+=x[i];
        printf("%d\n",ans);
        return;
    }
    else
    {
        int ans=0x3f3f3f3f;
        int tot=(1<<f);
        for(int i=0;i<tot;i++)
        {
            int cnt=0;
            for(int j=0;j<f;j++)
            {
                if(i&(1<<j))
                {
                    x[free_x[j]]=1;
                    cnt++;
                }
                else
                    x[free_x[j]]=0;
            }
            for(int j=var-f-1;j>=0;j--)
            {
                int idx;
                for(idx=j;idx<var;idx++)
                    if(a[j][idx])
                        break;
                x[idx]=a[j][var];
                for(int l=idx+1;l<var;l++)
                    if(a[j][l])
                        x[idx]^=x[l];
                cnt+=x[idx];
            }
            ans=min(ans,cnt);
        }
        printf("%d\n",ans);
    }
}
char p[30][30];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(p,‘\0‘,sizeof(p));
        int n;
        scanf("%d",&n);
        getchar();
        equ=n*n;
        var=n*n;
        init(n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",p[i]);
            for(int j=0;j<n;j++)
            {
                if(p[i][j]==‘y‘)
                    a[i*n+j][n*n]=0;
                else
                    a[i*n+j][n*n]=1;
            }
        }
        solve();
    }
    return 0;
}
				
时间: 2024-10-05 17:40:23

暑期实践日志(四)的相关文章

暑期实践日志(三)

开关问题 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6455   Accepted: 2463 Description 有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开.你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态.对于任意一个开关,最多只能进行一次开关操作

暑期实践日志(五)

这道题是典型的二维线段树的题目,题目要求查询一个区间的最小值和最大值,并修改一个点. 代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<set> #include<map> #include<cstdlib> u

暑期实践日志(二)

这道题的思路是,将题目中所描述的齿轮看成是圆,其中两个齿轮相互咬合则是两个圆相切,那么根据判断两个圆相切的方法来判断两个齿轮间是否咬合.其中还会用到齿轮传动的规律,即传动轮的速度由主动轮来决定,根据该题的描述可知所有齿轮中只有一个是主动轮,那么其他齿轮的速度都都它决定,随度的比值就是R1/Ri. 代码: #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #inc

暑期实践日志(一)

2015年7月6日 题解这道题目是一个数学题,其中有两个需要注意的地方. 第一:题目要求我们求将一个数分解成连续数字的和,而且要求数字个数最少.由题目意思可以推导出一个公式,所给的数N=(a+(a+k-1))/2.其中的a表示连续数字和中最小的那个数,k表示的是连续数字的个数,整个公式的由来是等差数列求和公式推导的. 第二:在求解时,虽然已经推导出了公式,但是在求解时,根据公式,我们采取遍历所有的k的值来求解a,如果从2到n遍历的话会超时.所以这里要注意,要从2到2*n开根号,这样可以避免超时.

浅谈SQL Server中的事务日志(四)----在完整恢复模式下日志的角色

浅谈SQL Server中的事务日志(四)----在完整恢复模式下日志的角色 本篇文章是系列文章中的第四篇,也是最后一篇,本篇文章需要前三篇的文章知识作为基础,前三篇的文章地址如下: 浅谈SQL Server中的事务日志(一)----事务日志的物理和逻辑构架 浅谈SQL Server中的事务日志(二)----事务日志在修改数据时的角色 浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色 简介 生产环境下的数据是如果可以写在资产负债表上的话,我想这个资产所占的数额一定不会

Agile实践日志一 -- Grooming Session

Agile实践日志一  -- Grooming Session GroomingSession 这个Session主要Go through我们下一个Sprint须要做的Story,大家都清楚之后,在每一个Story最后我们会以 Good Agile 扑克牌来确认它的难度点.在sprint之前,做一个story的评估和规划,为接下来分story提供难度系数的參照. Story Story是敏捷的核心.一切task来自story,我们仅仅有制定了story.才干确定task.一切測试工作也是基于st

JavaScript网站设计实践(四)编写about.html页面,利用JavaScript和DOM,选择性的显示和隐藏DIV元素

一.现在我们在网站设计(三)的基础上,来编写about.html页面. 这个页面要用到的知识点是利用JavaScript和DOM实现选择性地显示和隐藏某些DIV about.html页面在前面我们为了看导航栏菜单项高亮显示时,已经写了部分内容,只是那时写的代码没有实现div显示和隐藏,现在就在之前编写的基础上,为页面添加显示和隐藏div的效果. 没有写JavaScript之前看到的效果: 实现后的效果图: 这个就是我们现在要做的效果. 1.背景: 我们在about.html页面中写了一个ul列表

android 实践项目四

android 实践项目四 本周主要是开发android baidumap实现公交的查询 1.权限的取得和对屏幕的支持 1 <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" > 2 </uses-permission> 3 <uses-permission android:name="android.permission.ACCESS_NETWORK

Agile实践日志(2)-- Daily Stand up 和 Retrospective Session

Agile实践日志 (2) -- Daily Stand up 和 Retrospective Session 在Scrum开发过程中,会有三种会议: Grooming (详见Agile实践日志(1)) , Daily Stand up 和Retrospective Meeting Daily Stand up Sprint期间,每天早上小组成员需要在固定的时间地点进行,时间大约15分钟.主要介绍一下昨天做了什么,今天需要做什么,信心完成指数(1-10) Done 昨天完成的 ToDo 今天要做