题意:有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;
}
解法: 其实这个题目可以看成是一个隐式图搜索的问题 , 直接用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
{
};
struct node1
{
};
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()
{
}
void creat(int x , int y)
{
}
void dijkstra()
{
}
int main()
{
}