poj 1606 Jugs and poj 3414 Pots(数组模拟BFS) uva 571 (数论)

据说是水题,参考别人代码写了一个晚上。

题意是给两个水杯a<b,给定一个目标水量n,求用 fill A ,fill B ,empty A ,empty B ,pour A B ,pour B A,这几种方式,最少能几次倒出目标水量n。

因为用队列的stl要记录层比较难,所以用数组模拟。

代码:

#include <stdio.h>
#include <string.h>
const int MAX=1005;

int a,b,n,str[MAX*MAX],r,l;
bool vis[MAX][MAX];
char act[][10]= {" ","fill A","fill B","empty A","empty B","pour B A","pour A B"};

struct Point
{
    int va;
    int vb;
    int opr; //记录操作。
    int pre; //记录父结点。
} point[MAX*MAX];

void record(int va,int vb,int opr)
{
    if(vis[va][vb])
        return ;
    vis[va][vb]=1;
    point[r].va=va;
    point[r].vb=vb;
    point[r].opr=opr;
    point[r].pre=l;
    r++;
}

int min(int a,int b)
{
    return a>b?b:a;
}

void print()
{
    int top,i;
    top=0;
    while(l!=0)
    {
        str[top++]=point[l].opr; //因为数组可以记录下所有子结点和父结点,所以用队列写比较吃亏。
        l=point[l].pre;
    }

    for(i=top-1; i>=0; i--)
    {
        printf("%s\n",act[str[i]]);
    }
    printf("success\n");
}

void bfs()
{
    point[0].va=0;
    point[0].vb=0;
    vis[0][0]=1;

    l=0;
    r=1;

    while(1)
    {
        if(point[l].vb==n)
        {
            print();
            return ;
        }

        int xa,xb,x;
        //fill A
        xa=a;
        xb=point[l].vb;
        record(xa,xb,1);
        //fill B
        xa=point[l].va;
        xb=b;
        record(xa,xb,2);
        //empty A
        xa=0;
        xb=point[l].vb;
        record(xa,xb,3);
        //empty B
        xa=point[l].va;
        xb=0;
        record(xa,xb,4);
        //pour B A
        x=min(a-point[l].va,point[l].vb);
        xa=point[l].va+x;
        xb=point[l].vb-x;
        record(xa,xb,5);
        //pour A B
        x=min(b-point[l].vb,point[l].va);
        xa=point[l].va-x;
        xb=point[l].vb+x;
        record(xa,xb,6);

        l++;
    }
}

int main()
{
    while(scanf("%d%d%d",&a,&b,&n)!=EOF)
    {
        memset(vis,0,sizeof(vis));
        bfs();
    }
    return 0;
}


相同类型但是一直RE。。poj3414 T T

真脑残啊,一样的题目错了这么多遍。

但是也许acm迷人的地方也在这里。


题意与上题一样,不一样的地方就是impossible,和a b 大小不确定。

代码:

#include <stdio.h>
#include <string.h>
const int MAX=205;

int a,b,n,str[MAX*MAX],r,l;
bool vis[MAX][MAX];
char act[][10]= {" ","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(2,1)","POUR(1,2)"};
bool output;

struct Point
{
    int va;
    int vb;
    int opr; //记录操作。
    int pre; //记录父结点。
} point[MAX*MAX];

void record(int va,int vb,int opr)
{
    if(vis[va][vb])
        return ;
    vis[va][vb]=1;
    point[r].va=va;
    point[r].vb=vb;
    point[r].opr=opr;
    point[r].pre=l;
    r++;
}

int min(int a,int b)
{
    return a>b?b:a;
}

void print()
{
    int top,i;
    top=0;
    while(l!=0)
    {
        str[top++]=point[l].opr; //因为数组可以记录下所有子结点和父结点,所以用队列写比较吃亏。
        l=point[l].pre;
    }
    printf("%d\n",top);
    for(i=top-1; i>=0; i--)
    {
        printf("%s\n",act[str[i]]);
    }
}

void bfs()
{
    point[0].va=0;
    point[0].vb=0;
    vis[0][0]=1;

    l=0;
    r=1;

    while(l!=r)
    {
        if(point[l].vb==n||point[l].va==n)//!!不同点
        {
            output=1;
            print();
            return ;
        }

        int xa,xb,x;
        //fill A
        xa=a;
        xb=point[l].vb;
        record(xa,xb,1);
        //fill B
        xa=point[l].va;
        xb=b;
        record(xa,xb,2);
        //empty A
        xa=0;
        xb=point[l].vb;
        record(xa,xb,3);
        //empty B
        xa=point[l].va;
        xb=0;
        record(xa,xb,4);
        //pour B A
        x=min(a-point[l].va,point[l].vb);
        xa=point[l].va+x;
        xb=point[l].vb-x;
        record(xa,xb,5);
        //pour A B
        x=min(b-point[l].vb,point[l].va);
        xa=point[l].va-x;
        xb=point[l].vb+x;
        record(xa,xb,6);

        l++;
    }
}

int main()
{
    while(scanf("%d%d%d",&a,&b,&n)!=EOF)
    {
        if((a < n && b < n)||n==0)//!!不同点
        {
            printf("impossible\n");
            continue;
        }
        output=0;
        memset(vis,0,sizeof(vis));
        bfs();
        if(!output)              //!!不同点
            printf("impossible\n");
    }
    return 0;
}


uva 571:

题意同poj的,但思路不一样,这次是数论的思路。


解析:

用到了一个性质:r = k * a mod b,知a,b互素,必定可以得到区间(0, b - 1]的所有数。

所以只要不断模拟这个过程就行了,相当于往a倒水(*k),a中水倒入b内(mod b)。

注意执行顺序。


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;
const int maxn = 1e6;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif // LOCAL
    int ca, cb, n;
    while (scanf("%d%d%d", &ca, &cb, &n) != EOF)
    {
        int ta = 0;
        int tb = 0;
        while (1)
        {
            if (tb == n)
            {
                printf("success\n");
                break;
            }
            else if (tb == cb)
            {
                tb = 0;
                printf("empty B\n");
            }
            else if (ta == 0)
            {
                ta = ca;
                printf("fill A\n");
            }
            else if (ta != 0)
            {
                if (tb + ta <= cb)
                {
                    tb += ta;
                    ta = 0;
                }
                else
                {
                    ta = ta + tb - cb;
                    tb = cb;
                }
                printf("pour A B\n");
            }
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值