uva 10603 状态压缩& 最短路

本文介绍了一个经典的三杯水问题,并提供了一种基于隐式图搜索的解决方案。通过使用深度优先搜索(DFS)和最短路径算法,文章详细解释了如何构建状态转移图并求解目标状态所需的最小水量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值