uva 10603 状态压缩& 最短路

题意:有3个杯子 , 每个杯子的容量分别为: a 、 b、 c , 前两个杯子都是空的 , 第三个杯子的满的 , 问 ,让任意一个杯子中有确定L升水 , 最少需要倒多少升水。

解法: 其实这个题目可以看成是一个隐式图搜索的问题 , 直接用dfs就能解决 , 这里用最短路 , 那么我们就要先把图建立好 ,(a,b)这表示一个状态 , 那么我们把每个这样的状态看成是一个点 , 建图时 , 就判断这个点可以到达哪些点 , 如果能到达 ,就连一条有向边 , 边的权值为所倒水的多少。

代码:
#include
#include
#include
#include
#include
using namespace std;

#define maxn 210
#define INF 1000000000
#define min(x , y) (x)>(y)?(y):(x)
struct node
{
 
    int u;
 
    int d;
};

struct node1
{
 
    int d ,u;
 
    booloperator < (const node1 &rhs)const
 
    {
 
          return d>= rhs.d;
 
    }
};

vectorgrap[maxn*maxn];
int xy[maxn][maxn];
int a , b , c , d;
int dist[maxn*maxn] , pre[maxn*maxn];
int minx , my;

int n;

void init()
{
 
    int i ,j;
 
    for(i = 0; i<= c*c+1; i++)
 
          grap[i].clear();

 
    memset(xy ,-1 , sizeof(xy));
 
    int e =0;
 
    int x =min(c , a) , y = min(c , b);
 
    for(i = 0; i<= x; i++)
 
          for(j = 0; j<= y; j++)
 
                if(i+j<= c)
 
                      xy[i][j] =e++;

 
    n =e-1;

}

void creat(int x , int y)
{
 
   
 
    int z =c-x-y;
 
    int g =xy[x][y] , h;
 
    nodee;

 
    if(x> b-y)
 
    {
 
          h =xy[x-b+y][b];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =b-y;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    else
 
    {
 
          h =xy[0][x+y];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =x;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    if(x> c-z)
 
    {
 
          h =xy[x-c+z][y];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =c-z;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    else
 
    {
 
          h =xy[0][y];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =x;
 
                grap[g].push_back(e);
 
          }
 
    }


 
    if(y> a-x)
 
    {
 
          h =xy[a][y-a+x];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =a-x;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    else
 
    {
 
          h =xy[x+y][0];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =y;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    if(y> c-z)
 
    {
 
          h =xy[x][y-c+z];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =c-z;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    else
 
    {
 
          h =xy[x][0];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =y;
 
                grap[g].push_back(e);
 
          }
 
    }


 
    if(z> b-y)
 
    {
 
          h =xy[x][b];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =b-y;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    else
 
    {
 
          h =xy[x][z+y];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =z;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    if(z> a-x)
 
    {
 
          h =xy[a][y];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =a-x;
 
                grap[g].push_back(e);
 
          }
 
    }
 
    else
 
    {
 
          h =xy[x+z][y];
 
          if(h !=g)
 
          {
 
                e.u =h;
 
                e.d =z;
 
                grap[g].push_back(e);
 
          }
 
         
 
    }
}

void dijkstra()
{
 
    priority_queueq;
 
    int i ,j;

 
    node1e;
 
    nodef;

 
    e.d = 0 ,e.u = 0;
 
    q.push(e);
 
    for(i = 0; i<= n; i++) dist[i] = INF;
 
    memset(pre ,0 , sizeof(pre));
 
    dist[0] =0;
 
   
 
    while(!q.empty())
 
    {
 
          e =q.top();  q.pop();
 
          int u =e.u;

 
          if(pre[u])  continue;
 
          pre[u] =1;

 
          for(i = 0; i< grap[u].size(); i++)
 
          {
 
                f =grap[u][i];
 
                if(dist[u]+f.d < dist[f.u])
 
                {
 
                      dist[f.u] =dist[u]+f.d;
 
                      e.d =dist[f.u] ;
 
                      e.u =f.u;
 
                      q.push(e);
 
                     
 
                }
 
          }
 
    }
}

int main()
{
 
    int t;
 
    cin>>t;
 
    while(t--)
 
    {
 
          scanf("%d %d%d %d" , &a , &b ,&c , &d);

 
          if(c ==d)
 
          {
 
                printf("%d%d\n" , 0 , d);
 
                continue;
 
          }
 
          init();
 
         
 
          int i ,j;
 
          for(i = 0; i<= c; i++)
 
                for(j = 0; j<= c; j++)
 
                      if(xy[i][j]!= -1)  creat(i , j);


 
          dijkstra();
 
         
 
          int minx =INF;

 
          int x =min(a , c) , y = min(b , c);

 
          for(int k =d; k >= 0; k--)
 
          {
 
                minx =INF;
 
                for(i = 0; i<= x; i++)
 
                {
 
                      for(j = 0; j<= y; j++)
 
                            if(xy[i][j]!= -1 &&(i==k||j==k||(c-i-j)==k))
 
                                  minx =min(minx , dist[xy[i][j]]);
 
                }

 
                if(minx !=INF)
 
                {
 
                      printf("%d%d\n" , minx , k);
 
                      break;
 
                }
 
          }

 
         
 
    }
 
    return0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值