poj2814-拨钟问题-C语言-枚举算法

#include <stdio.h>  
#include <stdlib.h>  
/*  
首先,我们考虑用长度为9的数组表示表盘的状态以及调表的操作,终止的条件是表盘状态数组所有元素模4为0;  
如果一种操作使用超过4次,那么相当于没有操作,所以操作数组需要多出一位记录造作使用的次数,一个操作最多使用3次  
特别是我们注意到这个题没有问操作的顺序,所以操作的前后顺序其实是没有影响的;  
这样其实是对进行了哪些操作,操作了多少次进行枚举,也就是对一个9*4的矩阵进行枚举;并求矩阵行元素和的最小值,  
一共枚举4的9次方次  
*/  
short clocks[9],min=1000,operations[9][9],count[9],best[9];  
void change()//这个函数的作用是按照count调整clocks,并修改min,再把clocks改回去  
{  
    short i,j,flag=1,n=0;  
    for(i=0;i<9;i++)  
        n+=count[i];  
    if(n>=min) return;  
    for(i=0;i<9;i++)  
        for(j=0;j<9;j++)  
            clocks[j]+=(operations[i][j]*count[i]);  
    for(i=0;i<9;i++)  
    {  
        if((clocks[i]%4)!=0)  
            flag=0;  
    }  
    if(flag)  
    {  
        min=n;  
        for(i=0;i<9;i++)  
            best[i]=count[i];  
    }  
    for(i=0;i<9;i++)  
        for(j=0;j<9;j++)  
            clocks[j]-=(operations[i][j]*count[i]);  
}  
int main()  
{  
    operations[0][0]=operations[0][1]=operations[0][3]=operations[0][4]=1;  
    operations[1][0]=operations[1][1]=operations[1][2]=1;  
    operations[2][1]=operations[2][2]=operations[2][4]=operations[2][5]=1;  
    operations[3][0]=operations[3][3]=operations[3][6]=1;  
    operations[4][1]=operations[4][3]=operations[4][4]=operations[4][5]=operations[4][7]=1;  
    operations[5][2]=operations[5][5]=operations[5][8]=1;  
    operations[6][3]=operations[6][4]=operations[6][6]=operations[6][7]=1;  
    operations[7][6]=operations[7][7]=operations[7][8]=1;  
    operations[8][4]=operations[8][5]=operations[8][7]=operations[8][8]=1;  
    short i,j;  
    for(i=0;i<9;i++)  
        scanf("%d",&clocks[i]);  
    while(count[0]<4)  
    {  
        change();  
        count[8]++;  
        for(i=8;i>0;i--)  
        {  
            count[i-1]+=(count[i]/4);  
            count[i]=count[i]%4;  
        }  
    }  
    for(i=0;i<9;i++)  
        for(j=0;j<best[i];j++)  
            printf("%d ",i+1);  
    return 0;  
}  
原文地址:https://www.cnblogs.com/suway/p/7866187.html