zoukankan      html  css  js  c++  java
  • POJ 1753 Flip Game

    最近看了一篇讲acm技能树的文章 决定按照上面的顺序刷题

    文章链接:https://blog.csdn.net/qq_36345036/article/details/79860808

    第一题是一个暴力枚举的题

    题目链接:http://poj.org/problem?id=1753

    翻译一下就是有一个4*4的棋盘 棋子有黑白两面 w代表白色朝上 b代表黑色朝上

    每次翻转一个棋子 可以将它自己和上下左右四个棋子翻转

    问把棋盘变成全白或全黑的最少操作个数

    分析:

    对于一个棋子 只有翻转一次或者翻转0次 因为翻转奇数次和翻转1次相同 翻转2次和翻转偶数次相同

    棋盘的大小是确定的4*4 很小 所以我们可以直接枚举 翻转0个 看是否全白或全黑 翻转1个 看是否全白或全黑.............翻转16个 看是否全白或全黑

    所以本题的关键 是要找出 不同的棋盘位置的组合 进行判断

    而不同的组合 本质上就是求 从n个数中选取m个数的组合数 即Cmn

    至于怎么求组合数 我在前一篇文章已经写过了 直接套用就好了

    #include <stdio.h>    //POJ不支持bits/stdc++.h 真难受QAQ
    #include <stdlib.h>
    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    int flag=0,ms[4][4];
    
    void change(int newm[][4],int *b,int m)  //翻转
    {
        int i;
        for(i=0;i<m;i++)
        {
            int t=b[i];
            int tx=b[i]/4;
            int ty=b[i]%4;
            newm[tx][ty]=!newm[tx][ty];
            if(tx+1<4)
            newm[tx+1][ty]=!newm[tx+1][ty];
            if(ty+1<4)
            newm[tx][ty+1]=!newm[tx][ty+1];
            if(tx-1>=0)
            newm[tx-1][ty]=!newm[tx-1][ty];
            if(ty-1>=0)
            newm[tx][ty-1]=!newm[tx][ty-1];
        }
    }
    
    int panduan(int newm[][4])   //判断
    {
        int sflag=1,i,j;
        for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        if(newm[i][j]!=newm[0][0])
        {
            return 0;
        }
        return 1;
    }
    
    void digui(int *a,int *b,int t,int now,int n,int m)   //递归求组合数
    {
        int i,j;
        if(t==m)   
        {
            int newm[4][4];
            for(i=0;i<4;i++)
            for(j=0;j<4;j++)
            newm[i][j]=ms[i][j];   //创建一个棋盘的副本 避免影响原本的棋盘
            change(newm,b,m);
            if(panduan(newm))
            flag=1;
            return;
        }
        else
        {
            for(i=now;i<=n-(m-t);i++)
            {
                b[t]=a[i];
                digui(a,b,t+1,i+1,n,m);
            }
        }
    }
    
    int main()
    {
        int i,j;
        char m[4][4];
        int a[16]={0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15};
        int b[16];
        for(i=0;i<4;i++)
        {
            cin>>m[i];
            for(j=0;j<4;j++)
            {
                if(m[i][j]=='w')
                ms[i][j]=1;
                else
                ms[i][j]=0;
            }
        }
        for(i=0;i<=16;i++)
        {
            memset(b,0,sizeof(b));   //记得每次都要清零
            digui(a,b,0,0,16,i);
            if(flag==1)
            {
                cout<<i<<endl;
                break;
            }        
        }
        if(i==17)
        cout<<"Impossible"<<endl;
    }
  • 相关阅读:
    常忘知识点一:嵌套属性
    button按钮的状态为disabled禁用状态,click事件无法触发,但是为什么touchstart下却依然可以触发
    shell
    sql help cs
    再次写给我们这些浮躁的程序员
    C# winform进度条 (异步)
    关于C# WinForm中进度条的实现方法
    Oracle 多行记录合并/连接/聚合字符串的几种方法
    PL/SQL编码规范的一些建议
    PL/SQL 日期时间类型函数及运算
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/10920790.html
Copyright © 2011-2022 走看看