今天一天基本上都在找错误的过程中……
首先附昨天调试没通过的题:
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
- FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
- DROP(i) empty the pot i to the drain;
- POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.
3 5 4
6 FILL(2) POUR(2,1) DROP(1) POUR(2,1) FILL(2) POUR(2,1)
/*
1:Fill(1);给1倒满水
2:Fill(2);给2倒满水
3:Drop(1);倒空1
4:Drop(2);倒空2
5:Pour(1,2);1倒到2
6:Pour(2,1);2倒到1
*/
这个题的主要思路就是用广搜,执行操作。但这个题的难点是记录路径……
啊……又是记录路径的问题。
刚开始想了好久都没弄懂怎么记录路径,看了看题解,是用指针记录的。研究了一晚上,结果RE。。。不过那种方法能懂了,就不再细说了。
下面用到的方法是在该次操作的结构体对象内记录上一次的操作。
然后最后输出即可。
这个题的广搜不需要用到队列。
之前还有一个类似的倒可乐的例题。
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <stack>
using namespace std;
struct Tap
{
int nowa;
int nowb;
int oper;
int pre;
}tap[10000001];
int t,tail;
bool flag;
bool visit[1100][1100] ;
int shit[10000];
void Print()
{
int step = 0;
while (t != 0)
{
shit[step] = tap[t].oper;
step++;
t = tap[t].pre;
}
cout << step << endl;
for (int i = step - 1; i >= 0; i--)
{
int q = shit[i] ;
if (q == 1)
cout << "FILL(1)" << endl;
else if (q == 2)
cout << "FILL(2)" << endl;
else if (q == 3)
cout << "DROP(1)" << endl;
else if (q == 4)
cout << "DROP(2)" << endl;
else if (q == 5)
cout << "POUR(1,2)" << endl;
else if (q == 6)
cout << "POUR(2,1)" << endl;
}
return ;
}
void BFS(int a,int b,int c)
{
tap[0].nowa = 0;
tap[0].nowb = 0;
tap[0].oper = 0;
visit[tap[0].nowa][tap[0].nowb] = 1;
t = 0;
tail = 1;
int p1,p2;
while (t != tail)
{
if (tap[t].nowa == c || tap[t].nowb == c)
{
Print();
flag = 1;
break;
}
for (int i = 1; i <= 6; i++)
{
if (i == 1)
{
p1 = a;
p2 = tap[t].nowb;
if (!visit[p1][p2])
{
visit[p1][p2] = 1;
tap[tail].nowa = p1;
tap[tail].nowb = p2;
tap[tail].oper = i;
tap[tail++].pre = t;
}
}
else if (i == 2)
{
p1 = tap[t].nowa;
p2 = b;
if (!visit[p1][p2])
{
visit[p1][p2] = 1;
tap[tail].nowa = p1;
tap[tail].nowb = p2;
tap[tail].oper = i;
tap[tail++].pre = t;
}
}
else if (i == 3 )
{
p1 = 0;
p2 = tap[t].nowb;
if (!visit[p1][p2])
{
visit[p1][p2] = 1;
tap[tail].nowa = p1;
tap[tail].nowb = p2;
tap[tail].oper = i;
tap[tail++].pre = t;
}
}
else if (i == 4)
{
p1 = tap[t].nowa;
p2 = 0;
if (!visit[p1][p2])
{
visit[p1][p2] = 1;
tap[tail].nowa = p1;
tap[tail].nowb = p2;
tap[tail].oper = i;
tap[tail++].pre = t;
}
}
else if (i == 5)
{
p1 = tap[t].nowa - min(b - tap[t].nowb,tap[t].nowa);
p2 = tap[t].nowb + min(b - tap[t].nowb,tap[t].nowa);
if (!visit[p1][p2])
{
visit[p1][p2] = 1;
tap[tail].nowa = p1;
tap[tail].nowb = p2;
tap[tail].oper = i;
tap[tail++].pre = t;
}
}
else if (i == 6)
{
p1 = tap[t].nowa + min(a - tap[t].nowa,tap[t].nowb);
p2 = tap[t].nowb - min(a - tap[t].nowa,tap[t].nowb);
if (!visit[p1][p2])
{
visit[p1][p2] = 1;
tap[tail].nowa = p1;
tap[tail].nowb = p2;
tap[tail].oper = i;
tap[tail++].pre = t;
}
}
}
t++;
}
return ;
}
int main()
{
int a,b,c;
while(cin >> a >> b >> c)
{
memset(visit,0,sizeof(visit));
flag = false;
BFS(a,b,c);
if (flag == 0)
cout << "impossible" << endl;
}
return 0;
}
这个题的记录路径可是折腾了我好长时间。。。。对于我的帮助也比较大。。以后又多了一种记录路径的方式。
之前看C++ primer 的前面,着重看了看指针。这次用指针记录路径的方式,是我没有想到的。虽然RE,但指针依旧是一个非常重要的也是不太容易搞懂的东西。。。还需要继续研究。。
今天还A了两道题。。
比较郁闷的是今晚又找了一晚上错,最后发现错误竟然出现在最开始,二维数组的长和宽搞混了……而且第一组测试数据的长和宽正好一样。。。哇……真的……找了半天……
以后不能犯这种低级错误了……
发现已经有大佬快把练习AK了……感觉自己还是很菜
不过还是稳扎稳打继续努力吧。
附今天另外一个题:
Since the radio frequency spectrum is a precious resource, the number of channels required by a given network of repeaters should be minimised. You have to write a program that reads in a description of a repeater network and determines the minimum number of channels required.
2 A: B: 4 A:BC B:ACD C:ABD D:BC 4 A:BCD B:ACD C:ABD D:ABC 0
1 channel needed. 3 channels needed. 4 channels needed.
/*
相邻两个中继器不能使用同一个频道。
用map标记相邻的中继器;
搜索过程中判断相邻中继器是否使用同一个频道;
若没有频道可以用,频道增一;
若全搜索完,则输出需要的频道数;
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
char map[1000][1000];
int visit[2000];
int flag,ans,n;
int pd(int d,int c)
{
for (int k = 1; k <= n; k++)
if (map[d][k] == 1 && visit[k] == c)
return 0;
return 1;
}
void DFS(int d)
{
if (flag == 1)
return;
if (d == n + 1)
{
flag = 1;
if (ans == 1)
cout << ans << " channel needed." << endl;
else
cout << ans << " channels needed." << endl;
return ;
}
for (int i = 1; i <= ans; i++)
{
if (pd(d,i))
{
visit[d] = i;
DFS(d + 1);
visit[d] = 0;
}
}
ans += 1;
visit[d] = ans;
DFS(d + 1);
visit[d] = 0;
ans = ans - 1;
}
int main()
{
int i,j;
string a;
while(cin >> n)
{
if (n == 0)
break;
memset(map,0,sizeof(map));
memset(visit,0,sizeof(visit));
for (i = 1; i <= n; i++)
{
cin >> a;
if (a.length() > 2)
{
for (j = 2; j < a.length(); j++)
{
map[i][a[j] - 'A' + 1] = 1;
// cout << i << " " << a[j] - 'A' + 1 << endl;
}
}
}
flag = 0;
ans = 1;
DFS(1);
}
return 0;
}
还是要继续努力……