Fliptile POJ-3279 DFS

本文解析了一个关于01矩阵翻转的问题,目标是最少步骤将矩阵变为全0矩阵。通过确定首行状态并递推计算后续行翻转情况,找到最优解。

题目链接:Fliptile

题目大意

有一个01矩阵,每一次翻转(0->1或者1->0)一个元素,就会把与他相邻的四个元素也一起翻转。求翻转哪些元素能用最少的步骤,把矩阵变成0矩阵。

思路

假设确定了第一行的状态,那么第二行需要翻转的所有元素都能确定(上一行如果是1就必须翻转)。因此对于所有第一排的情况,往下递推需要翻转的元素,最后判断最后一行如果全为0则满足条件,记录步骤最少的情况。

题解

  1 #include <iostream>
  2 #include <cstring>
  3 
  4 using namespace std;
  5 
  6 int n, m, mmin=0x3f3f3f3f;
  7 int map[20][20],tmp[20][20],ans[20][20];
  8 
  9 bool judge(){
 10     for(int i = 0 ; i < m; i++)
 11     {
 12         int time = tmp[n-2][i] + tmp[n-1][i];
 13         if(i != 0)
 14         {
 15             time += tmp[n-1][i-1];
 16         }
 17         if(i != m-1)
 18         {
 19             time += tmp[n-1][i+1];
 20         }
 21         time %= 2;
 22         if(map[n-1][i] ^ time){
 23             return false;
 24         }
 25     }
 26     return true;
 27 }
 28 
 29 void dfs(int k, int num)
 30 {
 31     if(num > mmin) return;
 32     if(k > n-1)    //最后一行遍历    结束,判断最后一行是否全0
 33     {
 34         if(judge() && num < mmin)
 35         {
 36             memcpy(ans, tmp, sizeof(tmp));
 37             mmin = num;
 38         }
 39         return;
 40     }
 41     int flag = 0;
 42     
 43     for(int i = 0; i < m; i++)
 44     {
 45         int time = 0;
 46         time = tmp[k-1][i] + tmp[k-2][i];
 47         if(i != 0)
 48         {
 49             time += tmp[k-1][i-1];
 50         }
 51         if(i != m-1)
 52         {
 53             time += tmp[k-1][i+1];
 54         }
 55         if((map[k-1][i]+time)&1)
 56         {
 57             tmp[k][i] = 1;
 58             flag++;
 59         }
 60         else
 61         {
 62             tmp[k][i] = 0;
 63         }
 64     }
 65     dfs(k+1, num+flag);        //搜索下一行
 66 }
 67 
 68 void todfs(int k, int num)
 69 {
 70     if(k > m - 1){    //遍历完第一行
 71         dfs(1, num);    //从第二行开始
 72         return;
 73     }
 74     tmp[0][k] = 0;
 75     todfs(k+1, num);
 76     tmp[0][k] = 1;
 77     todfs(k+1, num+1);
 78 }
 79 
 80 int main(int argc, char const *argv[])
 81 {
 82 #ifdef debug
 83     freopen("test.txt","r",stdin);
 84 #endif
 85     cin >> n >> m;
 86     for(int i = 0; i < n; i++)
 87     {
 88         for (int j = 0; j < m; j++)
 89         {
 90             cin >> map[i][j];
 91         }
 92     }
 93     todfs(0, 0);
 94     if(mmin == 0x3f3f3f3f)
 95     {
 96         cout << "IMPOSSIBLE" << endl;
 97     }
 98     else
 99     {
100         for(int i = 0; i < n; i++)
101         {
102             for(int j = 0; j < m; j++)
103             {
104                 cout << ans[i][j] << " ";
105             }
106             cout << endl;
107         }
108     }
109     return 0;
110 }

其实这个题用的数组下标最好是从1开始,这样不用把列号是0的元素拿出来单独计算了。

转载于:https://www.cnblogs.com/SaltyFishQF/p/10296750.html

「LLM那些事」系列第 4 篇《上下文窗口的边界》,文章连接:https://blog.csdn.net/houwenjin/article/details/163999753。 演示什么:在「预测」Sheet 的黄色格子里输入一句话(默认「来泡一杯」),四个「模型」——分别只统计最后 1 / 2 / 3 / 4 个字的 n-gram 查表——同时预测下一个字。同一个输入,看的上下文越长,候选越少、预测越确定: ┌────────────────┬──────────┬───────────────┬──────┐ │ 只看最后几个字 │ 用的前缀 │ 候选下一字数 │ 预测 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 1 个 │ 杯 │ 3(茶/子/水) │ 模糊 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 2 个 │ 一杯 │ 2(茶/水) │ 收窄 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 3 个 │ 泡一杯 │ 1(茶) │ 确定 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 4 个 │ 来泡一杯 │ 1(茶) │ 确定 │ └────────────────┴──────────┴───────────────┴──────┘
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 笔记本的散热风扇管理 ---------------------------------------- 09 November 2006. 对于版本20061109的变更概述如下: 1) ACPI CA核心子系统:在源操作数是一个操作区域的场景下,对负载ASL操作符进行了优化。仅需映射操作区域内存,而不是执行逐字节读取。 (区域必须为SystemMemory类型,见下文。)修正了源操作数为区域字段的负载ASL操作符问题。也允许缓冲区对象作为源操作数。 BZ 480 解决了负载ASL操作符允许源操作数为任意类型操作区域的问题。现被限制为仅SystemMemory类型的区域,符合ACPI规范。 BZ 481 对新表管理器代码进行了额外的清理和优化。AcpiEnable将在所有必需的ACPI表未加载时失败(FADT, FACS, DSDT)。 BZ 477 在acobject.h中添加了#pragma pack(8/4),以确保此头文件中的结构始终编译为对齐。ACPI_OPERAND_OBJECT已被手动优化为对齐,并在字节打包时无法工作。示例代码和数据大小:这些是Microsoft Visual C++ 6.0 32位编译器生成的、与操作系统无关的acpica.lib的大小。调试版本的代码包含调试输出跟踪机制,具有更大的代码和数据大小。上一个版本:非调试版本:78.1K代码,17.1K数据,95.2K总计 调试版本:155.4K代码,63.1K数据,218.5K总计 当前版本:非调试版本:77.9K代码,17.0K数据,94.9K总计 调试版本:155.2K代码,63.1K数据,...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值