HDU 1495 非常可乐 数论

Problem Description

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

Input

三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。

Output

如果能平分的话请输出最少要倒的次数,否则输出"NO"。

Sample Input

7 4 3
4 1 3
0 0 0

Sample Output

NO
3

Author

seeyou

Source

“2006校园文化活动月”之“校庆杯”大学生程序设计竞赛暨杭州电子科技大学第四届大学生程序设计竞赛

Analysis

因为瓶子是没有刻度的,所以说N 和 M是基本单位(并非最小单位),即所有可能的结果都是基于N 和 M。比如说,假设N > M,可以通过S -> N,N -> M来得到N—M,重复类似操作,得到的结果可以一般地表示为xN + yM,a 和 b为整数,x 和 y表示对N瓶和M瓶的操作数(两者不含重复部分)。

Solution

在这里插入图片描述

Code

    #include <cstdio>
    #include <algorithm>
    int main()
    {
        int s, n, m;
        while(scanf("%d%d%d", &s, &n, &m)==3 && s+n+m){
            s /= std :: __gcd(n, m);
            if(s&1) printf("NO\n");
            else printf("%d\n", s-1);
        }
        return 0;
	 }

PS.

0.数论方法吹爆,核心代码不过五行!!!(自然不是我这种蒟蒻想出来的。)
1.用到的数论知识:裴蜀定理,二元一次不定方程的通解。
2.抄来的DFS打印具体方案(大,中,小3个杯子的容量分别为a,b,c,最初只有大杯子装满水,其他两个杯子为空。给出最少需要步数的方案让某一个杯子中的水有x升)以及两组辅助理解的数据


    /*
    因为给出条件后3个杯子中水的总量同时确定,所以可以减少用于记录的数组维数。使用递归的方法遍历可能经过的所有路径并记录可到达的最短步数
    */
    #include<iostream>
    #include<string.h>
    using namespace std;
    struct node{
    	int par[2];
    		//存储到达该节点处上一个节点的位置
    	int value;
    		//到该节点为止转移次数
    };
    int a,b,c;
    struct node path[1000][1000];
    	// 仅存储两个杯子的水量,用以节省空间
    void fun(int cura,int curb,int curc){
    	//转移算法,使用递归方法
    	int cura1,curb1,curc1;
    	if(cura!=a){
    		if((cura+curb)>a){
    			cura1=a;curb1=cura+curb-cura1;curc1=curc;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		else{
    			cura1=cura+curb;curb1=0;curc1=curc;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		if((cura+curc)>a){
    			cura1=a;curb1=curb;curc1=cura+curc-cura1;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		else{
    			cura1=cura+curc;curb1=curb;curc1=0;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    	}
    	if(curb!=b){
    		if(cura+curb>b){
    			cura1=cura+curb-b;curb1=b;curc1=curc;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		else{
    			cura1=0;curb1=cura+curb;curc1=curc;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		if(cura+curc>c){
    			cura1=cura+curc-c;curb1=curb;curc1=c;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		else{
    			cura1=0;curb1=curb;curc1=cura+curc;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    
    	}
    	if(curc!=c){
    		if((cura+curc)>c){
    			cura1=cura+curb-c;curb1=curb;curc1=c;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		else{
    			cura1=0;curb1=curb;curc1=curc+cura;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		if((curb+curc)>c){
    			cura1=cura;curb1=curb+curc-c;curc1=c;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    		else{
    			cura1=cura;curb1=0;curc1=curc+curb;
    			if(path[curb1][curc1].value==-1||(path[curb1][curc1].value>path[curb][curc].value+1)){
    				path[curb1][curc1].par[0]=curb;path[curb1][curc1].par[1]=curc;
    				path[curb1][curc1].value=path[curb][curc].value+1;
    				fun(cura1,curb1,curc1);
    			}
    		}
    	}
    }
    	//打印出转移路线
    void print(struct node a1){
    	if(a1.par[0]==-1&&a1.par[1]==-1);//......
    	else{
    		print(path[a1.par[0]][a1.par[1]]);
    		cout<<a-a1.par[0]-a1.par[1]<<'\t'<<a1.par[0]<<'\t'<<a1.par[1]<<endl;
    	}
    }
    int main(){
    	int x,min,k,mk;struct node minb;
    	while(cin>>a>>b>>c){
    		for(int i=0;i<1000;i++)
    			for(int j=0;j<1000;j++){
    				path[i][j].par[0]=path[i][j].par[1]=path[i][j].value=-1;
    			}
    		path[0][0].value=0;
    		fun(a,0,0);
    			//遍历所有转移路线
    		cin>>x;
    			{
    				min=1000,minb;
    				for(k=0;k<=a-x;k++){
    					if(path[k][a-x-k].value!=-1&&path[k][a-x-k].value<min){
    						min=path[k][a-x-k].value;
    						minb=path[k][a-x-k];
    						mk=k;
    					}
    				}
    					//在转移路线中查找最短路径
    				if(min==1000)
    					cout<<"Not found"<<endl;
    				else{
    					cout<<min<<endl;
    					print(minb);
    					cout<<x<<'\t'<<mk<<'\t'<<a-x-mk<<endl;
    				}
    			}
    
    	}
    	return 0;
    }
    

	/*
    8 5 3
    4
    7
    8       0       0
    3       5       0
    3       2       3
    6       2       0
    6       0       2
    1       5       2
    1       4       3
    4       4       0
    30 27 3
    15
    9
    30      0       0
    3       27      0
    3       24      3
    6       24      0
    6       21      3
    9       21      0
    9       18      3
    12      18      0
    12      15      3
    15      15      0
    */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值