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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值