problem 1005

    题目大概99.9%的人都听说过:

    两个杯子(A 、B)用不完的水,一共有六种操作:1、加满A(B),2、清空A(B),3、将A(B)中的水倒入B(A)(加满为止)。不断的做这些操作,最终达到B中剩下指定量的水。

    输入:        A的容积,B的容积,以及最终要求B中剩下多少水(不会出现无解的情况)

    输出:        操作步骤(这里并不要求最少步骤)

    考虑回溯搜索,这里显然有很多可以剪枝的地方:

       1、不能出现重复的情况 

       2、清空后加满不如直接加满,加满后清空不如直接清空

       3、操作后不能出现全满和全空的情况

Accepted1005C++00:00.064300K

#include<stdio.h>
#include
<string.h>
#define B         if(blacklist[a][b] == 0)   /      
                
{                        /         
                    stack[top][
0=
 a;       /      
                    stack[top][
1=
 b;       /      
                    top
++
;                   /      
                    blacklist[a][b]
++
;       /       
                    
continue
;                /     
                }
                            /     
                
else
                         /    
                
{                        /         
                    a 
=
 a1;                  /       
                    b 
=
 b1;                  /       
                }

int  ca,cb,n;
int stack[100][2
];
int
 top;
int blacklist[1000][1000
];
int getoperate(int
 index)
{
    
if(index > 0
)
    
{
        
int t = stack[index - 1][0+ stack[index - 1][1
];
        
int t1 = stack[index][0+ stack[index][1
];
        
if(t ==
 t1)
            
if(stack[index][0==
 ca)
                
return 2
;
            
else if(stack[index][1== 0
)
                
return 2
;
            
else return 1
;
        
else if(t1 >
 t)
            
return stack[index][0== ca ? 3 : 4
;
        
else if(t1 <
 t)
            
return stack[index][0== 0 ? 5 : 6
;
    }

    
return 0;
}

void  print()
{
    
for(int i = 1; i < top; i++
)
    
{
        
switch
(getoperate(i))
        
{
        
case 1
:
            printf(
"pour A B");break
;
        
case 2
:
            printf(
"pour B A");break
;
        
case 3
:
            printf(
"fill A");break
;
        
case 4
:
            printf(
"fill B");break
;
        
case 5
:
            printf(
"empty A");break
;
        
case 6
:
            printf(
"empty B");break
;
        }

        printf(
" ");
    }

}

void  search()
{
    
int
 a,b,a1,b1;
    a 
= b = 0
;
    a1 
= b1 = 0
;
    memset(blacklist,
0,sizeof
(blacklist));
    memset(stack,
0,sizeof
(stack));
    top 
= 0
;
    stack[top][
0= 0
;
    stack[top][
1= 0
;
    blacklist[ca][cb] 
= 1
;
    blacklist[
0][0= 1
;
    top
++
;
    
while(1
)
    
{
        
if(a - cb + b==
 n)
        
{
            print();
            printf(
"pour A B empty B pour A B "
);
            
return
;
        }

        
if(b - ca + a == n)
        
{
            print();
            printf(
"pour B A "
);
            
return
;
        }


        a1 
= a;
        b1 
=
 b;
        
if(a > cb - b)//1 pour a b 

        {
            a 
= a - cb +
 b;
            b 
=
 cb;
        }

        
else
        
{
            b 
= a +
 b;
            a 
= 0
;
        }

        B

        a1 
= a;
        b1 
=
 b;
        
if(b > ca - a)//2 pour b a

        {
            b 
= b - ca +
 a;
            a 
=
 ca;
        }

        
else
        
{
            a 
= a +
 b;
            b 
= 0
;
        }

        B
        
if(getoperate(top - 1!= 5)//3 fill a
        {
            a1 
=
 a;
            b1 
=
 b;

            a 
=
 ca;
            B
        }

        
if(getoperate(top - 1!= 6)//4 fill b
        {
            a1 
=
 a;
            b1 
=
 b;
            b 
=
 cb;
            B
        }
        

        
if(getoperate(top - 1!= 3)//5 empty a

        {
            a1 
=
 a;
            b1 
=
 b;
            a 
= 0
;
            B
        }

        
if(getoperate(top - 1!= 4)//6 empty b
        {
            a1 
=
 a;
            b1 
=
 b;
            b 
= 0
;
            B
        }

        top
--;//back
        a = stack[top - 1][0];
        b 
= stack[top - 1][1
];
    }

}

void  solve()
{
    
int
 i;
    
if(cb ==
 n)
    
{
        printf(
"fill B "
);
        
return
;
    }

    
if(n % ca == 0)
    
{
        
for(i = 0; i < n/ca; i++
)
            printf(
"fill A pour A B "
);
        
return
;
    }

    
if(cb - ca == n)
    
{
        printf(
"fill B pour B A "
);
        
return
;
    }

    search();
}

int  main()
{
#ifndef ONLINE_JUDGE
    freopen(
"1005.txt","r"
,stdin);
#endif

    
while(scanf("%d%d%d",&ca,&cb,&n) != EOF)
    
{
        solve();
        printf(
"success "
);
    }

#ifndef ONLINE_JUDGE
    fclose(stdin);
#endif
    
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值