专注 效率 记忆
预习 笔记 复习 做题
欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)
文章字体风格:
红色文字表示:重难点★✔
蓝色文字表示:思路以及想法★✔
如果大家觉得有帮助的话,感谢大家帮忙
点赞!收藏!转发!
本博客带大家一起学习,我们不图快,只求稳扎稳打。
由于我高三是在家自学的,经验教训告诉我,学习一定要长期积累,并且复习,所以我推出此系列。
只求每天坚持40分钟,一周学5天,复习2天
也就是一周学10道题
60天后我们就可以学完81道题,相信60天后,我们一定可以有扎实的代码基础!我们每天就40分钟,和我一起坚持下去吧!
qq群:878080619
因为数字本身可能会重复出现,而且对于一个字符串交换它两个不同相邻位置得到的新字符串,也可能产生重复,但我们要求的是最少交换次数,因为BFS的性质,保证了可以实现最小,所以可以设置一个map映射组,来存储已经出现过的字符串情况,防止重复对相同组成的字符串再入队处理,以作到剪枝的作用,降低时间复杂度。
这道题进入BFS暴搜前,要做一些基本的判断,很容易就考虑不到,要做好了。
#include
#include
#include
#include
#include
using namespace std;
int n;
int bfs(string start)
{
queue<string> q;
unordered_map<string, int> dist;
dist[start] = 0;
q.push(start);
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < n; i ++ )
if (t.substr(i, 4) == "2012")
return dist[t];
for (int i = 1; i < n; i ++ )
{
string r = t;
swap(r[i], r[i - 1]);
if (!dist.count(r))
{
dist[r] = dist[t] + 1;
q.push(r);
}
}
}
return -1;
}
int main()
{
string start;
cin >> n >> start;
cout << bfs(start) << endl;
return 0;
}
根据样例分析出
只要每行有两个元素
那么该行就能推出所有等差数据
同理列也是
所以我们先遍历所有行和列
看哪些有两个元素的
然后根据这样行和列进行填充
填充过程中观察是否新数据使得对应的行或者列
变得大于两个元素,进而可以填充
那么该过程就想到了bfs
bfs队列存储的元素是什么呢?就是所在的行或者列
怎么判断是行还是列呢?
行的范围为(0-n)
列的范围(n,m+n)
#include
#include
#include
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 1010, M = N * 2;
int n, m;
int row[N], col[N];
int q[M], hh, tt = -1;
bool st[M];
PII ans[N * N];
int top;
int g[N][N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
{
scanf("%d", &g[i][j]);
if (g[i][j])
{
row[i] ++ ;
col[j] ++ ;
}
}
for (int i = 0; i < n; i ++ )
if (row[i] >= 2 && row[i] < m)
{
q[ ++ tt] = i;
st[i] = true;
}
for (int i = 0; i < m; i ++ )
if (col[i] >= 2 && col[i] < n)
{
q[ ++ tt] = i + n;
st[i + n] = true;
}
while (hh <= tt)
{
auto t = q[hh ++ ];
if (t < n) // 行
{
PII p[2];
int cnt = 0;
for (int i = 0; i < m; i ++ )
if (g[t][i])
{
p[cnt ++ ] = {i, g[t][i]};
if (cnt == 2) break;
}
int d = (p[1].y - p[0].y) / (p[1].x - p[0].x);
int a = p[1].y - d * p[1].x;
for (int i = 0; i < m; i ++ )
if (!g[t][i])
{
g[t][i] = a + d * i;
ans[top ++ ] = {t, i};
col[i] ++ ;
if (col[i] >= 2 && col[i] < m && !st[i + n])
{
q[ ++ tt] = i + n;
st[i + n] = true;
}
}
}
else // 列
{
t -= n;
PII p[2];
int cnt = 0;
for (int i = 0; i < n; i ++ )
if (g[i][t])
{
p[cnt ++ ] = {i, g[i][t]};
if (cnt == 2) break;
}
int d = (p[1].y - p[0].y) / (p[1].x - p[0].x);
int a = p[1].y - d * p[1].x;
for (int i = 0; i < n; i ++ )
if (!g[i][t])
{
g[i][t] = a + d * i;
ans[top ++ ] = {i, t};
row[i] ++ ;
if (row[i] >= 2 && row[i] < n && !st[i])
{
q[ ++ tt] = i;
st[i] = true;
}
}
}
}
sort(ans, ans + top);
for (int i = 0; i < top; i ++ )
{
auto& p = ans[i];
printf("%d %d %d\n", p.x + 1, p.y + 1, g[p.x][p.y]);
}
return 0;
}
#include
#include
#include
using namespace std;
int main()
{
string s;
getline(cin, s);
for (int i = 0; i < s.size(); i ++ )
if (!i || s[i - 1] == ' ')
cout << (char)toupper(s[i]);
else
cout << s[i];
return 0;
}
#include
#include
#include
#include
using namespace std;
const int N = 10010;
int n;
string logs[N];
int main()
{
while (getline(cin, logs[n]))
if (logs[n].size()) n ++ ;
else break;
sort(logs, logs + n, [](string& a, string &b) {
stringstream ssina(a), ssinb(b);
string sa[4], sb[4];
for (int i = 0; i < 4; i ++ )
{
ssina >> sa[i];
ssinb >> sb[i];
}
if (sa[3] == sb[3]) return sa[1] + sa[2] < sb[1] + sb[2];
double ta, tb;
sscanf(sa[3].c_str(), "%lf(s)", &ta);
sscanf(sb[3].c_str(), "%lf(s)", &tb);
return ta < tb;
});
for (int i = 0; i < n; i ++ )
cout << logs[i] << endl;
return 0;
}
#include
#include
#include
#include
using namespace std;
typedef long long LL;
int main()
{
string s;
cin >> s;
for (int i = 0; i < s.size(); i ++ )
if (isdigit(s[i]))
{
LL x = 0;
while (i < s.size() && isdigit(s[i]))
{
x = x * 10 + s[i] - '0';
if (x > INT_MAX)
{
puts("-1");
return 0;
}
i ++ ;
}
cout << x << endl;
return 0;
}
puts("-1");
return 0;
}
所以需要递归
#include
#include
#include
#include
using namespace std;
int n;
vector<string> p;
vector<string> g(int k)
{
if (k == 1) return p;
auto s = g(k - 1);
int m = s.size();
vector<string> res(n * m);
for (int i = 0; i < n * m; i ++ )
res[i] = string(n * m, ' ');
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
if (p[i][j] != ' ')
for (int x = 0; x < m; x ++ )
for (int y = 0; y < m; y ++ )
res[i * m + x][j * m + y] = s[x][y];
return res;
}
int main()
{
while (cin >> n, n)
{
p.clear();
getchar(); // 读掉n后的回车
for (int i = 0; i < n; i ++ )
{
string line;
getline(cin, line);
p.push_back(line);
}
int k;
cin >> k;
auto res = g(k);
for (auto& s: res) cout << s << endl;
}
return 0;
}
#include
#include
#include
using namespace std;
const int N = 1010;
int n, m;
int f[N][N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ )
{
int v, w;
scanf("%d%d", &v, &w);
for (int j = 0; j <= m; j ++ )
{
f[i][j] = f[i - 1][j];
if (j >= v)
f[i][j] = max(f[i][j], f[i - 1][j - v] + w);
}
}
printf("%d\n", f[n][m]);
return 0;
}
#include
using namespace std;
const int N = 50;
int f[N][N];
int a[N];
int n;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
f[0][0] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= 40; j++)
{
f[i][j] = f[i-1][j];
if(a[i]<=j)
{
f[i][j] = f[i][j] + f[i-1][j-a[i]];
}
}
}
cout << f[n][40];
return 0;
}
#include
using namespace std;
typedef long long LL;
const int N = 1e6+10, mod = 1e9;
LL v[25], f[25][N]; //v[]:存储 2 的 i 次幂,即 2^i
void init(){ //预处理出 2 的 0 次幂到 20 次幂
v[0] = 1;
for(int i = 1;i <= 20;++i) v[i] = v[i - 1] * 2;
}
void solve(){
int n;
cin >> n;
init();
for(int i = 0;i <= 20;++i){
for(int j = 0;j <= n;++j){
if(!i || !j){ //状态为 f[i][0] 和 f[0][j] 时,将其初始化为 1
f[i][j] = 1;
continue;
}
if(j < v[i]) f[i][j] = f[i - 1][j]; //当 2^i > j 时,f[i][j]中只有一个集合(有0个 2^i 的集合)
else f[i][j] = (f[i - 1][j] + f[i][j - v[i]]) % mod; //状态转移方程
}
}
cout << f[20][n];
}
int main(){
solve();
return 0;
}
#include
#include
#include
using namespace std;
const int N = 1000010, MOD = 1e9;
int n;
int f[N];
int main()
{
scanf("%d", &n);
f[0] = 1;
for (int i = 1; i <= n; i *= 2)
for (int j = i; j <= n; j ++ )
f[j] = (f[j] + f[j - i]) % MOD;
cout << f[n] << endl;
return 0;
}
#include
#include
#include
#include
using namespace std;
const int N = 1010;
vector<int> F[N];
vector<int> mul(vector<int>& A, int b)
{
vector<int> C;
for (int i = 0, t = 0; i < A.size() || t; i ++ )
{
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
return C;
}
int main()
{
int n;
F[0] = {1};
for (int i = 1; i <= 1000; i ++ ) F[i] = mul(F[i - 1], i);
while (cin >> n)
{
for (int i = F[n].size() - 1; i >= 0; i -- )
cout << F[n][i];
cout << endl;
}
return 0;
}
#include
#include
#include
#include
using namespace std;
int add(vector<int>& A, vector<int>& B)
{
int res = 0;
for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i ++ )
{
if (i < A.size()) t += A[i];
if (i < B.size()) t += B[i];
t /= 10;
res += t;
}
return res;
}
int main()
{
string a, b;
while (cin >> a >> b, a != "0" || b != "0")
{
vector<int> A, B;
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');
int res = add(A, B);
if (!res) puts("No carry operation.");
else if (res == 1) puts("1 carry operation.");
else printf("%d carry operations.\n", res);
}
return 0;
}
#include
#include
#include
#include
using namespace std;
vector<int> add(vector<int>& A, vector<int>& B)
{
vector<int> C;
for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i ++ )
{
if (i < A.size()) t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
return C;
}
int main()
{
vector<int> A{0};
string b;
while (cin >> b, b != "0")
{
vector<int> B;
for (int i = b.size() - 1; i >= 0; i -- )
B.push_back(b[i] - '0');
A = add(A, B);
}
while (A.size() > 1 && !A.back()) A.pop_back();
for (int i = A.size() - 1; i >= 0; i -- )
cout << A[i];
cout << endl;
return 0;
}