F - 暴力出奇迹

The Center City fire department collaborates with the transportation department to maintain maps of the city which reflects the current status of the city streets. On any given day, several streets are closed for repairs or construction. Firefighters need to be able to select routes from the firestations to fires that do not use closed streets.

Central City is divided into non-overlapping fire districts, each containing a single firestation. When a fire is reported, a central dispatcher alerts the firestation of the district where the fire is located and gives a list of possible routes from the firestation to the fire. You must write a program that the central dispatcher can use to generate routes from the district firestations to the fires.

Input

The city has a separate map for each fire district. Streetcorners of each map are identified by positive integers less than 21, with the firestation always on corner #1. The input file contains several test cases representing different fires in different districts.

The first line of a test case consists of a single integer which is the number of the streetcorner closest to the fire.The next several lines consist of pairs of positive integers separated by blanks which are the adjacent streetcorners of open streets. (For example, if the pair 4 7 is on a line in the file, then the street between streetcorners 4 and 7 is open. There are no other streetcorners between 4 and 7 on that section of the street.)The final line of each test case consists of a pair of 0's.

Output

For each test case, your output must identify the case by number (CASE #1CASE #2, etc). It must list each route on a separate line, with the streetcorners written in the order in which they appear on the route. And it must give the total number routes from firestation to the fire. Include only routes which do not pass through any streetcorner more than once. (For obvious reasons, the fire department doesn't want its trucks driving around in circles.)

Output from separate cases must appear on separate lines.

The following sample input and corresponding correct output represents two test cases.

Sample Input

6
1 2
1 3
3 4
3 5
4 6
5 6
2 3
2 4
0 0
4
2 3
3 4
5 1
1 6
7 8
8 9
2 5
5 7
3 1
1 8
4 6
6 9
0 0

Sample Output

CASE 1:
1 2 3 4 6
1 2 3 5 6
1 2 4 3 5 6
1 2 4 6
1 3 2 4 6
1 3 4 6
1 3 5 6
There are 7 routes from the firestation to streetcorner 6.
CASE 2:
1 3 2 5 7 8 9 6 4
1 3 4
1 5 2 3 4
1 5 7 8 9 6 4
1 6 4
1 6 9 8 7 5 2 3 4
1 8 7 5 2 3 4
1 8 9 6 4
There are 8 routes from the firestation to streetcorner 4.
PS:一开始直接dfs暴力,结果超时了

原来可能有一些点很明显不能到达终点的,但直接dfs,它会算进去,增加了时间

所以在dfs前加了bfs,找出可以到终点的点

在dfs时,遇到不是这些点的就可以直接剪掉,于是就AC了


代码:

#include<iostream>
#include<string.h>
#include<queue>
using namespace std;

int map[25][25] = { 0 };
int num[25] = { 1 };
int flag[25] = { 0 };
int vis[25] = { 0 };
int cou = 0, m;

void dfs(int cur)
{
	if (num[cur - 1] == m)
	{
		cou++;
		for (int i = 0; i < cur - 1; ++i)
		{
			cout << num[i] << " ";
		}
		cout << num[cur - 1] << endl;
	}
	else
	{
		for (int i = 2; i <= 21; ++i)
		{
			if (!flag[i] && vis[i] && map[num[cur - 1]][i])
			{
				num[cur] = i;
				flag[i] = 1;
				dfs(cur + 1);
				flag[i] = 0;
			}
		}
	}
}

queue<int> q;

void bfs()
{
	q.push(m);
	while (!q.empty())
	{
		int p = q.front();
		q.pop();
		for (int i = 1; i <= 21; ++i)
		{
			if (map[p][i] && !vis[i])
			{
				q.push(i);
				vis[i] = 1;
			}
		}
	}
	vis[m] = 1;
}

int main()
{
	int k = 1;
	while (cin >> m)
	{
		int a, b;
		cou = 0;
		memset(flag, 0, sizeof(flag));
		memset(map, 0, sizeof(map));
		memset(vis, 0, sizeof(vis));
		while (cin >> a >> b&&a&&b)
		{
			map[a][b] = 1;
			map[b][a] = 1;
		}
		cout << "CASE " << k++ << ":\n";
		bfs();
		dfs(1);
		cout << "There are " << cou << " routes from the firestation to streetcorner " << m << ".\n";
	}

	return 0;
}





### 计蒜客 T1684 狂暴石 C++ 暴力解法 为了实现该问题的暴力解法,可以通过枚举所有可能的选择组合来找到最优解。以下是详细的解决方案: #### 解决思路 由于需要考虑所有的子集情况(除了全不选的情况外),可以利用二进制表示方法遍历所有可能的子集。对于每一个子集,分别计算其对应的愤怒值乘积和暴躁值之和,并记录两者差值绝对值最小的结果。 需要注意的是,在处理愤怒值时可能会遇到零或者负数的情况,因此要特别注意初始化条件以及边界情况的处理[^1]。 #### 实现代码 以下是一个基于上述思路编写的 C++ 暴力求解程序: ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; vector<int> anger(n); vector<int> irritability(n); for (int i = 0; i < n; ++i) { cin >> anger[i]; } for (int i = 0; i < n; ++i) { cin >> irritability[i]; } long long min_diff = LLONG_MAX; // 遍历所有非空子集 for (int mask = 1; mask < (1 << n); ++mask) { long long product_anger = 1, sum_irritability = 0; bool valid_subset = false; for (int j = 0; j < n; ++j) { if ((mask & (1 << j)) != 0) { valid_subset = true; product_anger *= anger[j]; sum_irritability += irritability[j]; } } if (!valid_subset) continue; long long diff = abs(product_anger - sum_irritability); if (diff < min_diff) { min_diff = diff; } } cout << min_diff << endl; } ``` 此代码通过位掩码的方式实现了对所有非空子集的穷举操作,并针对每个有效子集计算了愤怒值的乘积与暴躁值的加和之间的差异,最终输其中最小的那个差异值。 #### 复杂度分析 时间复杂度主要由两部分构成:一是外部循环迭代次数为 \(2^n\);二是内部嵌套循环用于检查当前掩码下哪些位置被激活,最坏情况下每次都需要扫描整个数组长度即 O(n),所以总体的时间复杂度大约为 \(O(2^n \times n)\)。这种算法适合于较小规模的数据输入场景。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值