问题描述:
解题思路:
题目说可以挑选任意个操作,因此我们枚举全部的子集。题目说以任意顺序执行,因此我们枚举每种子集的全排列。如果存在一种子集的一种排列可以使s变成t就返回yes并结束,反之,遍历完全部没有找到结果就输出No。
注意点:1.枚举全排列方法:
sort(list.begin(), list.end());
do{//.... }while(next_permutation(list.begin(), list.end()));
2.枚举子集的方法:二进制,k表示位数,也是元素总数。i:每种子集的二进制表示
for(int i = 0; i < (1 << k); i++){vector<int> list; // vector放在局部变量位置,每次循环都会重置为空*,当放在全局变量位置就不会重置 for(int j = 0; j < k; j++){if((1 << j) & i)list.push(j); // j就表示一种子集的其中一个元素,把全部元素放入数组就是一种子集 }
}
代码:
#include<bits/stdc++.h>
using namespace std;
int a[10][4];
string s, t;bool check(vector<int> list){ // 检查当前排列是否使S变为Tfor(int i: list){ // 进行操作的编号if(a[i][1] == 1){s[a[i][2]] = (s[a[i][2]] - '0' + a[i][3]) % 10 + '0'; // ascii执行操作1}else{swap(s[a[i][2]], s[a[i][3]]);}}//比较字符串if(t.find(s) != string::npos)return true;else return false; // 要加个return,不然不会出现报错但有样例不过
}int main()
{int n;cin >> n;cin >> s >> t;int k;cin >> k;for(int i = 0; i < k; i++){cin >> a[i][1] >> a[i][2] >> a[i][3];}for(int i = 0; i < (1 << k); i++){vector<int> list; // 存放每种子集for(int j = 0; j < k; j++){if((1 << j) & i)list.push_back(j); // 123: 1, 12, 13....123(每次i循环一种子集)}sort(list.begin(), list.end()); // 全排列:需要先排序在使用next_permutationdo{if(check(list)){puts("Yes");return 0;} }while(next_permutation(list.begin(), list.end())); // 找到下一个排列可能}puts("No");return 0;
}
知识点:全排列,枚举子集,ascii