nyoj-三个水杯

三个水杯

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
2
6 3 1
4 1 1
9 3 2
7 1 1
样例输出
3
-1
来源
经典题目
上传者
hzyqazasdf


写这道题的时候我就觉得是一道数学题

于是我试着用数学思想解决他

于是  我有了点发现

三个水杯中,如果三个水杯最终状态都是不满的     无解

............其他的毫无规律

还是老老实实用广搜吧!

为什么不用深搜那?

应为我们不知道应该搜到什么时候可以停止了

一直向下搜,死循环 ,一直互相倒水,银河二号也要超时

如果定一个边界,如搜到第几次还不行就换一条路的话  你也不知道这个边界定在哪里合适,短了容易吧正确答案省掉    长了  容易超时

还不如广搜,没这么多顾虑

#include<stdio.h>
#include<string.h>
int e1,e2,e3;
int i,j,k=0,l=1,need;
bool vis[100][100][100];
struct node
{
    int v[3];
    int step;
} sb[200];
void ds(int a,int b)
{
    if(sb[k].v[a]!=0&&vis[sb[k].v[0]][sb[k].v[1]][sb[k].v[2]]==false)  //判断能否倒水和是否出现过此状态
    {
        int sum=sb[k].v[a]+sb[k].v[b];             //下面开始倒水
        if(sum>=sb[k].v[b])
        {
            sb[l].v[b]=sb[0].v[b];
            sb[l].v[a]=sum-sb[l].v[b];
        }
        else
        {
            sb[l].v[b]=sum;
            sb[l].v[a]=0;
        }
        sb[l].step=sb[k].step+1;
        l++;
    }
}
int bfs(int v1,int v2,int v3)
{
    for(k=0;; k++) //将队列从头遍历到尾
    {
        //printf("%d %d %d\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]);
        for(i=0; i<3; i++)      //遍历6种倒水情况
        {
            for(j=0; j<3; i++)
            {
                if(i!=j)
                {
                    ds(i,j);       //倒水函数  将i中的水往  j中倒
                }
            }
        }
        if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2])    //如果过程达到了目标状态  那就return  步数
        {
            return sb[k].step;
        }
    }
    return -1;       //如果队列都遍历完了  那么就 没有结果  返回-1
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int v1,v2,v3,e1,e2,e3;
        scanf("%d%d%d%d%d%d",&sb[0].v[0],&sb[0].v[1],&sb[0].v[2],&e1,&e2,&e3);
        k=0,sb[0].step=0;              //初始化
        memset(vis,false,sizeof(vis));
        printf("%d\n",bfs(sb[0].v[0],sb[0].v[1],sb[0].v[2]));
    }
}
直接出错!!!

for(j=0; j<3; i++)
多明显的错误~

#include<stdio.h>
#include<string.h>
int v0[3],e1,e2,e3;
int i,j,k=0,l=1,need;
bool vis[100][100][100];
struct node
{
    int v[3];
    int step;
} sb[200];
void ds(int a,int b)
{
    if(sb[k].v[a]!=0)  //判断能否倒水和是否出现过此状态
    {
        sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2];
        int sum=sb[k].v[a]+sb[k].v[b];             //下面开始倒水
        if(sum>=v0[b])
        {
            sb[l].v[b]=v0[b];
            sb[l].v[a]=sum-v0[b];
        }
        else
        {
            sb[l].v[b]=sum;
            sb[l].v[a]=0;
        }
        if(vis[sb[k].v[0]][sb[k].v[1]][sb[k].v[2]]==false)
        {
            //printf(" %d\n",l);
            sb[l].step=sb[k].step+1;
            l++;
            vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=true;
            //rintf("%d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2]);
        }
    }
}
int bfs(int v1,int v2,int v3)
{
    for(k=0;; k++) //将队列从头遍历到尾
    {
        //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]);
        for(i=0; i<3; i++)      //遍历6种倒水情况
        {
            for(j=0; j<3; j++)
            {
                //printf("%d %d***\n",i,j);
                if(i!=j)
                {
                    ds(i,j);       //倒水函数  将i中的水往  j中倒
                }
            }
        }
        if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2])    //如果过程达到了目标状态  那就return  步数
        {
            return sb[k].step;
        }
    }
    return -1;       //如果队列都遍历完了  那么就 没有结果  返回-1
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3);
        k=0,sb[0].step=0;
        sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0;              //初始化
        memset(vis,false,sizeof(vis));
        printf("%d\n",bfs(sb[0].v[0],0,0));
    }
}
明显的,这排重就没起作用!!!!

好吧,把排重步骤的顺序改一下

#include<stdio.h>
#include<string.h>
int v0[3],e1,e2,e3;
int i,j,k=0,l=1,need;
int vis[105][105][105];
struct node
{
    int v[3];
    int step;
} sb[50000];
void ds(int a,int b)
{
    if(sb[k].v[a]!=0)  //判断能否倒水
    {
        sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2];
        int sum=sb[k].v[a]+sb[k].v[b];             //下面开始倒水
        if(sum>=v0[b])
        {
            sb[l].v[b]=v0[b];
            sb[l].v[a]=sum-v0[b];
        }
        else
        {
            sb[l].v[b]=sum;
            sb[l].v[a]=0;
        }
        //printf("%d  0.0\n",vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]);
        if(vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]==0)    //判断是否出现过此状态
        {
            //printf(" %d\n",l);
            sb[l].step=sb[k].step+1;
            vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=1;
            l++;
            //printf("%d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2]);
        }
    }
}
int bfs(int v1,int v2,int v3)
{
    for(k=0;; k++) //将队列从头遍历到尾
    {
        //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]);
        for(i=0; i<3; i++)      //遍历6种倒水情况
        {
            for(j=0; j<3; j++)
            {
                //printf("%d %d***\n",i,j);
                if(i!=j)
                {
                    ds(i,j);       //倒水函数  将i中的水往  j中倒
                }
            }
        }
        if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2])    //如果过程达到了目标状态  那就return  步数
        {
            return sb[k].step;
        }
        if(k>l)
        {
            return -1;   //如果队列都遍历完了  那么就 没有结果  返回-1
        }
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3);
        if(e1+e2+e3!=v0[0])
        {
            printf("-1\n");
        }
        else if(v0[0]==e1&&v0[1]==e2&&v0[2]==e3)
        {
            printf("0\n");
        }
        else
        {
            k=0,sb[0].step=0;
            sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0;              //初始化
            memset(vis,0,sizeof(vis));
            printf("%d\n",bfs(sb[0].v[0],0,0));
        }
    }
}
哎  

if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2])    //如果过程达到了目标状态  那就return  步数
这个错误又找了很久

#include<stdio.h>
#include<string.h>
int v0[3],e1,e2,e3;
int i,j,k=0,l=1,need;
int vis[105][105][105];
struct node
{
    int v[3];
    int step;
} sb[100000]
void ds(int a,int b)
{
    if(sb[k].v[a]!=0)  //判断能否倒水
    {
        sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2];
        int sum=sb[k].v[a]+sb[k].v[b];             //下面开始倒水
        if(sum>=v0[b])
        {
            sb[l].v[b]=v0[b];
            sb[l].v[a]=sum-v0[b];
        }
        else
        {
            sb[l].v[b]=sum;
            sb[l].v[a]=0;
        }
        //printf("%d  0.0\n",vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]);
        if(vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]==0)    //判断是否出现过此状态
        {
            //printf(" %d\n",l);
            sb[l].step=sb[k].step+1;
            vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=1;
            l++;
            //printf("%d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2]);
        }
    }
}
int bfs(int v1,int v2,int v3)
{
    for(k=0;; k++) //将队列从头遍历到尾
    {

        //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]);
        for(i=0; i<3; i++)      //遍历6种倒水情况
        {
            for(j=0; j<3; j++)
            {
                //printf("%d %d***\n",i,j);
                if(i!=j)
                {
                    ds(i,j);       //倒水函数  将i中的水往  j中倒
                    if(sb[l-1].v[0]==e1&&sb[l-1].v[1]==e2&&sb[l-1].v[2]==e3)    //如果过程达到了目标状态  那就return  步数
                    {
                        return sb[l-1].step;
                    }
                }
            }
        }
        if(k>l)
        {
            return -1;   //如果队列都遍历完了  那么就 没有结果  返回-1
        }
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3);
        if(e1+e2+e3!=v0[0])
        {
            printf("-1\n");
        }
        else if(v0[0]==e1&&v0[1]==e2&&v0[2]==e3)
        {
            printf("0\n");
        }
        else
        {
            k=0,sb[0].step=0;
            sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0;              //初始化
            memset(vis,0,sizeof(vis));
            printf("%d\n",bfs(sb[0].v[0],0,0));
        }
    }
}
....还有一个问题 

样例

6 4 3

3 3 0

输出应该是2

但是是3

不是最小情况

要是再加入一个min找最下  那么很可能就会超时!!


哇喀喀喀!终于AC了

#include<stdio.h>
#include<string.h>
int v0[3],e1,e2,e3;
int i,j,k=0,l=1,need;
int vis[105][105][105];
struct node
{
    int v[3];
    int step;
} sb[100000];
void ds(int a,int b)
{
    if(sb[k].v[a]!=0)  //判断能否倒水
    {
        sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2];
        int sum=sb[k].v[a]+sb[k].v[b];             //下面开始倒水
        if(sum>=v0[b])
        {
            sb[l].v[b]=v0[b];
            sb[l].v[a]=sum-v0[b];
        }
        else
        {
            sb[l].v[b]=sum;
            sb[l].v[a]=0;
        }
        //printf("%d 0.0\n",vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]);
        if(vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]==0)    //判断是否出现过此状态
        {
            //printf(" %d\n",l);
            sb[l].step=sb[k].step+1;
            vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=1;
            l++;
            //printf("%d %d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2],sb[l-1].step);
        }
    }
}
int bfs(int v1,int v2,int v3)
{
    for(k=0;; k++) //将队列从头遍历到尾
    {
        //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]);
        for(i=0; i<3; i++)      //遍历6种倒水情况
        {
            for(j=0; j<3; j++)
            {
                //printf("%d %d***\n",i,j);
                if(i!=j)
                {
                    ds(i,j);       //倒水函数  将i中的水往  j中倒
                    if(sb[l-1].v[0]==e1&&sb[l-1].v[1]==e2&&sb[l-1].v[2]==e3)    //如果过程达到了目标状态  那就return  步数
                    {
                        return sb[l-1].step;
                    }
                }
            }
        }
        if(k>l)
        {
            return -1;   //如果队列都遍历完了  那么就 没有结果  返回-1
        }
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3);
        if(e1+e2+e3!=v0[0])
        {
            printf("-1\n");
        }
        else if(v0[0]==e1)
        {
            printf("0\n");
        }
        else
        {
            k=0,sb[0].step=0,l=1;
            sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0;              //初始化
            memset(vis,0,sizeof(vis));
            printf("%d\n",bfs(sb[0].v[0],0,0));
        }
    }
}
这题我dbug  了好几天  可能是我太水了!!!

可我一直坚持自己dbug!!!

不看网上代码!

激动坏了!!!1





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
孪生素数是指两个素数之间的差值为2的素数对。通过筛选法可以找出给定素数范围内的所有孪生素数的组数。 在引用的代码中,使用了递归筛选法来解决孪生素数问题。该程序首先使用循环将素数的倍数标记为非素数,然后再遍历素数数组,找出相邻素数之间差值为2的素数对,并统计总数。 具体实现过程如下: 1. 定义一个数组a[N,用来标记数字是否为素数,其中N为素数范围的上限。 2. 初始化数组a,将0和1标记为非素数。 3. 输入要查询的孪生素数的个数n。 4. 循环n次,每次读入一个要查询的素数范围num。 5. 使用两层循环,外层循环从2遍历到num/2,内层循环从i的平方开始,将素数的倍数标记为非素数。 6. 再次循环遍历素数数组,找出相邻素数之间差值为2的素数对,并统计总数。 7. 输出总数。 至此,我们可以使用这个筛选法的程序来解决孪生素数问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python用递归筛选法求N以内的孪生质数(孪生素数)](https://blog.csdn.net/weixin_39734646/article/details/110990629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [NYOJ-26 孪生素数问题](https://blog.csdn.net/memoryofyck/article/details/52059096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值