拉了个搜索专题,这是第一道题。虽然之前就见过,可一直没有思路,这次重新写,终于AC。
思路就是把这个问题模型转换成三维坐标中的点,倒可乐就是坐标的变换,只要坐标满足条件即是可乐平分成功。
可乐奇数直接NO,然后广搜,广搜里的两层for也是一个技巧
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define el else
typedef long long LL;
struct point{
int total;
int a;
int b;
int st;
point(int t,int aa,int bb,int ss)
:total(t),a(aa),b(bb),st(ss)
{}
};
const int maxn = 102;
bool vis[maxn][maxn][maxn];
int V[3];
int S,N,M;
int bfs(){
point t(S,0,0,0);
stack<point> s;
s.push(t);
while(!s.empty()){
t = s.top(); s.pop();
int a[3];
//printf("t = %d %d %d\n",t.total,t.a,t.b);////
if(t.a == S/2 && t.b == 0 || t.b == S/2 && t.a == 0){
//printf("total = %d, a = %d, b = %d\n",t.total,t.a,t.b);////
return t.st;
}
for(int i=0; i<3; ++i){
for(int j=0; j<3; ++j)
{
a[0] = t.total, a[1] = t.a, a[2] = t.b;
//printf("i = %d,a[i] = %d\n",i,a[i]);////
//printf("j = %d,a[j] = %d\n",j,a[j]);////
if(i != j && a[i]>0 && a[j]<V[j])
{
//puts("in");////
if(a[i] >= V[j]-a[j]){
a[i] -= (V[j]-a[j]);
a[j] = V[j];
}//倒的比容量大
else{
a[j] += a[i];
a[i] = 0;
}//能到的没容量大
if(!vis[ a[0] ][ a[1] ][ a[2] ]){
vis[ a[0] ][ a[1] ][ a[2] ] = 1;
point shit(a[0],a[1],a[2],t.st+1);
//printf("shit = %d %d %d\n",shit.total,shit.a,shit.b);///
s.push(shit);
}
}
}
}
}
return -1;
}
int main(){
while(scanf("%d%d%d",&S,&N,&M),S!=0){
if(S & 1){
puts("NO");
continue;
}
if(N > M) N ^= M,M ^= N,N ^= M;
V[0]=S, V[1]=N, V[2]=M;
memset(vis,0,sizeof(vis));
int step = bfs();
step == -1 ? puts("NO") : printf("%d\n",step);
}
return 0;
}
But...Wait!
这个题还可以用数论来写,摘自:https://blog.youkuaiyun.com/V5ZSQ/article/details/52097459
所以|x+|y|的最小值为(c+d)/2,通过x和y的通解形式显然可以看出x和y一正一负,不妨设x<0,那么就是往第一个小瓶子倒进x次,第二个小瓶子倒出y次,但是由于瓶子容积有限,所以倒进倒出操作都是通过大瓶子来解决的,一次倒进操作后为了继续使用小瓶子还要将小瓶子中可乐倒回大瓶子中,倒出操作同理,所以总操作次数是(c+d)/2*2=c+d,但是注意最后剩下的(a+b)/2体积的可乐一定是放在两个小瓶子中较大的那个中,而不是再倒回到大瓶子中,所以操作数要减一,答案就是c+d-1
---------------------
作者:v5zsq
来源:优快云
原文:https://blog.youkuaiyun.com/V5ZSQ/article/details/52097459
版权声明:本文为博主原创文章,转载请附上博文链接!
#include<cstdio>
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int a,b,c;
while(scanf("%d%d%d",&a,&b,&c),a+b+c)
{
a/=gcd(b,c);
if(a&1)printf("NO\n");
else printf("%d\n",a-1);
}
return 0;
}