AtCoder Beginner Contest 332

C- t-shirts

分析:遇到s1尽量穿普通衣服,普通t没有了就穿标志t,标志t也没了就要买一件。

遇到s2必须穿标志t,没有了就买一件。

最少买多少件,取决与两个s0天之间的日子,要买多少件t

void solve() {
	int n, m; cin >> n >> m;
	string s; cin >> s;

	int pm = m;
	int cnt = 0;
	int pc = 0;
	for (int i = 0; i < s.size(); i++) {
		if (s[i] == '1') {
			if (pm == 0) {
				if (pc == 0) {
					cnt++;
				}
				else {
					pc--;
				}
			}
			else {
				pm--;
			}
		}
		else if (s[i] == '2') {
			if (pc == 0) {
				cnt++;
			}
			else {
				pc--;
			}
		}
		else {
			pc = cnt; pm = m;
		}
	}

	cout << cnt;
}

D - Swapping Puzzle

分析:关注一下数据量,特别特别小,因此可以用暴力dfs枚举所有情况,求全排列,这里用next_permutation全排列函数来枚举所有情况,效果和自己手写dfs的效果是一样的。

1)两个数组,r和c数组,rc 分别表示数组a的行和列的索引,用来存行和列变换的状态。一会nex_permutation就是对这两个数组操作,枚举所有行和列变换的情况。

2)如果经过变换后的a等于b(注意,不是真的对数组a进行变换,而是变换了r和c数组实现“伪变换”,因为变换r和c数组后,我们就可以知道变换后的a的样子),我们就去算a变换了多少次。

逆序对的个数就是变换次数,这里不证明了。

ps:要注意行和列都只能和相邻的交换!当时就是题目没看清浪费了很多时间

int a[10][10], b[10][10]; int n, m;
int r[6] = { 0,1,2,3,4,5 };
int c[6] = { 0,1,2,3,4,5 };
bool check(int e1[10][10],int e2[10][10]) {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (e1[i][j] != e2[i][j]) return false;
		}
	}
	return true;
}
void solve() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> a[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> b[i][j];
		}
	}

	int ans = inf;
	//注意是相邻交换!
	do {//用do-while是因为,可能一次也不变换
		do {
			if (check(a, b)) {
				int num = 0;
				for (int i = 1; i <= n; i++) {
					for (int j = 1; j <= n; j++) {
						if (i<j && r[i]>r[j]) {
							num++;
						}
					}
				}

				for (int i = 1; i <= m; i++) {
					for (int j = 1; j <= m; j++) {
						if (i<j && c[i]>c[j]) {
							num++;
						}
					}
				}

				ans = min(ans, num);
			}


		} while (next_permutation(c + 1, c + 1 + m));
	} while (next_permutation(r + 1, r + 1 + n));

	//tans; 
	if (ans == inf) cout << -1 << endl;
	else cout << ans << endl;
}

最后附上next_permutation的用法

next_permutation 是 C++ STL 中的一个函数,用于求一个序列的下一个排列。下面是它的基本用法:

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
  std::vector<int> v{1, 2, 3};

  do {
    for (auto i : v) {
      std::cout << i << ' ';
    }
    std::cout << '\n';
  } while (std::next_permutation(v.begin(), v.end()));

  return 0;
}

这段代码会输出 1 2 3、1 3 2、2 1 3、2 3 1、3 1 2、3 2 1 这六个排列。

next_permutation 的参数是一个迭代器区间,表示一个序列。它返回值是一个 bool 类型,表示是否找到了序列的下一个排列。如果找到了下一个排列,则函数会直接修改原序列。

如果想按照自定义排序规则来求下一个排列,可以使用自定义比较函数。比如,将上面的代码改为按照字典序升序排列:

#include <algorithm>
#include <iostream>
#include <vector>

bool my_compare(int a, int b) {
  return a > b;
}

int main() {
  std::vector<int> v{3, 2, 1};

  do {
    for (auto i : v) {
      std::cout << i << ' ';
    }
    std::cout << '\n';
  } while (std::next_permutation(v.begin(), v.end(), my_compare));

  return 0;
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值