1 高精度

注意 printf(""%Lf",a);不需要取地址

1)R问题

https://www.lanqiao.cn/problems/19710/learning/

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    string d;    //数太大用字符数组读
    cin >> n >> d;
    vector<int>b;  //开vetor好处就是可以用push_back进位的时候可以在后面直接加
    int sum = 0, k = 0;
    for (int i = d.size() - 1;i >= 0;i--)
    {
        if (d[i] != '.')
            b.push_back(d[i] - '0');   //把字符型变成整数型 
        else { k = sum; }//sum 用于记录当前处理的是第几位数字
        sum++;   //找到小数点位置为以后输出做铺垫,现在就可以看作一个大整数了
    }
    int u = b.size();
    //这里相当于模拟了高精度大数乘小数
    while (n--)   //指数类型太大,保存不了,故每次*2 
    {
        int t = 0;
        for (int i = 0;i < b.size();i++)
        {
            b[i] = b[i] * 2 + t;   //t是进位的数
            if (b[i] >= 10)
            {
                t = b[i] / 10;
                b[i] = b[i] % 10;
            }
            else t = 0;
        }
        if (t)
            b.push_back(t);
    }   //模拟数学过程 
    u = b.size();
    int t = 1;
    if (k && b[k - 1] >= 5) {     // 四舍五入过程,如果存在小数点(k 不为 0),并且小数点后第一位(b[k - 1])大于等于 5
        for (int i = k;i < u;i++)
        {
            b[i] = b[i] + 1;
            if (b[i] <= 9) { t = 0;break; }
            else b[i] -= 10;
        }
        if (t) b.push_back(t);
        //注意余数处理
    }
    for (int i = b.size() - 1;i >= k;i--)
        cout << b[i];
    return 0;
}

2深搜

1)路径数字接龙

https://www.lanqiao.cn/problems/19712/learning/

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const int N = 11; // 定义棋盘的最大大小为11×11
int n, k; // n为棋盘大小,k为数字循环的范围
int g[N][N]; // 存储棋盘上的数字
int dx[8] = { -1, -1, 0, 1, 1, 1, 0, -1 }; // 定义8个方向的x坐标偏移
int dy[8] = { 0, 1, 1, 1, 0, -1, -1, -1 }; // 定义8个方向的y坐标偏移
string path; // 存储路径的方向编号
bool st[N][N]; // 标记棋盘上的格子是否被访问过
bool edge[N][N][N][N]; // 检查路径是否交叉

// 深度优先搜索函数,用于寻找路径
bool dfs(int a, int b) {
    // 如果到达右下角格子,检查路径长度是否为n*n-1(因为起点不计入路径)
    if (a == n - 1 && b == n - 1)
        return path.size() == n * n - 1;

    st[a][b] = true; // 标记当前格子已访问
    for (int i = 0; i < 8; i++) { // 遍历8个方向
        int x = a + dx[i], y = b + dy[i]; // 计算目标格子的坐标
        // 检查目标格子是否越界、是否访问过、数字是否满足循环序列要求
        if (x < 0 || x >= n || y < 0 || y >= n) continue;
        if (st[x][y]) continue;
        if (g[x][y] != (g[a][b] + 1) % k) continue;
        // 检查路径是否交叉(对于斜向移动,检查是否有反向的路径)
        if (i % 2 && (edge[a][y][x][b] || edge[x][b][a][y])) continue;

        edge[a][b][x][y] = true; // 标记路径
        path += i + '0'; // 将方向编号加入路径
        if (dfs(x, y)) return true; // 递归搜索下一个格子
        /*
        即使深层递归返回 true,当前层如果没有及时返回,
        就会继续执行其他方向的尝试,而回溯会覆盖已经找到的路径。
        例如,当某个方向找到了正确路径,当前层的 dfs 函数应该立即返回 true,
        让上层知道已经找到解,从而终止搜索。
        如果没有 if 语句,当前层会继续处理其他方向,可能导致路径被覆盖或重复计算。*/
        path.pop_back(); // 回溯,移除路径中的最后一个方向
        edge[a][b][x][y] = false; // 回溯,取消路径标记
    }
    st[a][b] = false; // 回溯,取消当前格子的访问标记
    return false; // 如果所有方向都无法到达终点,返回false
}

int main() {
    cin >> n >> k; // 输入棋盘大小和数字循环范围
    for (int i = 0; i < n; i++) // 读取棋盘上的数字
        for (int j = 0; j < n; j++)
            cin >> g[i][j];

    // 从起点(0,0)开始搜索路径
    if (!dfs(0, 0))
        cout << -1 << endl; // 如果没有找到路径,输出-1
    else
        cout << path << endl; // 输出路径的方向编号序列

    return 0;
}

3 双指针

1)拔河

解法一:前缀和暴力得出所有解,然后遍历每种相邻的解,选出差值最小的,如果重叠就相当于没选重叠部分。

点击查看代码
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int N=1e3+10;
int n,js=1,a[N],check[N*N];
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++){//我们先通过二层循环,暴力出每一种选法
        int s=0;
        for(int j=i;j<=n;j++){
            s+=a[j];
            check[js++]=s;
        }
    }//可能有谁都不选的选法,check数组从0开始
    sort(check,check+js);
    //将他们从小到大排序,力量值之和差距最小的一定是相邻的两种选法
    //不用管区间选择重叠的情况,重叠部分相当于两种选法都没选重叠部分
    int ans=1e12+10;
    for(int i=1;i<js;i++)ans=min(ans,check[i]-check[i-1]);
    cout<<ans;
    return 0;
}

解法二:双指针,通过++实际实现了四个指针。我当时想直接用双指针,但是头尾指针,感觉会限制在头尾选,或者要有两个区间感觉需要四个指针这里就是四个指针,lr指定了从哪开始,然后通过++指定了延申到哪。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 4;
int n;
vector<ll>a(N);
int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 1;i <= n;i++)  cin >> a[i];
    ll ans = 1e14;

    for (int l = 1;l <= n;l++)
    {
        for (int r = n;r > l;r--)
        {
            //双指针 i 和 j 分别指向区间的左右端点
            /*
            我当时想直接用双指针,但是头尾指针,感觉会限制在头尾选,或者要有两个区间感觉需要四个指针
            这里就是四个指针,lr指定了从哪开始,然后通过++指定了延申到哪/
            */
            int i = l, j = r;
            ll sum1 = a[i], sum2 = a[j];
            ans = min(ans, abs(sum1 - sum2));
            if (ans == 0)
            {
                cout << 0;
                return 0;
            }
            while (i + 1 <= j)
            {
                if (sum1 == sum2)
                {
                    cout << 0;
                    return 0;
                }
                if (sum1 > sum2)
                {
                    j--;
                    sum2 += a[j];
                }
                else if (sum1 < sum2)
                {
                    i++;
                    sum1 += a[i];
                }
                ans = min(ans, abs(sum1 - sum2));
            }
        }
    }
    cout << ans;
    return 0;
}
理解错误,给出的数不一定要全部选
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
const int maxn = 1e3 + 10;
int a[maxn];
int sum[maxn];
int ans1, ans2;
int ans = 1e9 + 1;

signed main()
{
	cin >> n;
	for (int i = 1;i <= n;i++)
		cin >> a[i];
	for (int i = 1;i <= n;i++)
	{
		sum[i] += sum[i - 1] + a[i];
	}
	for (int i = 1;i <= n;i++)
	{
		ans1 = sum[i];
		ans2 = sum[n] - sum[i];
		ans = min(abs(ans1 - ans2), ans);
	}
	cout << ans;
}

2)子序列问题

https://www.lanqiao.cn/problems/3492/learning/

很典型但是没想到咋做,双指针,匹配主串++,不匹配子串++。仍旧是吧答案列出来,然后倒退每个答案是否符合

点击查看代码
#include<bits/stdc++.h>
using namespace std;
string s;
int mon[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12 };
int day[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
string str = "5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1 0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3";
int ans = 0;
bool check(string ss) {
    int i = 0; // 主字符串的指针
    int j = 0; // 待匹配字符串的指针
    while (i < str.length() && j < ss.length()) {
        if (str[i] == ss[j]) {
            j++; // 若字符相同,移动待匹配字符串的指针
        }
        i++; // 始终移动主字符串的指针
    }
    return j == ss.length(); // 若待匹配字符串的指针遍历完,说明包含

}
signed main() {

    for (int i = 1;i <= 12;i++)
    {
        for (int j = 1;j <= day[i];j++)
        {
            string mo = to_string(mon[i]);
            string da = to_string(j);
            if (i < 10)
                mo = "0" + mo;
            if (j < 10)
                da = "0" + da;
            s = "";
            s += "2023" + mo + da;
            //这里没重置s产生累加问题
            if (check(s) == 1)
                ans++;
           


        }
    }
    cout << ans << endl;





}

3 暴力枚举

1)01串计算

https://www.lanqiao.cn/problems/3498/learning/

需要注意fabs是取浮点数的绝对值,然后就是log2可以直接调用数学函数。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int main() {
    double n = 23333333, sum = 0;
    double ans = 11625907.5798;
    double minn = 100.0;
    int st;
    for (int i = 0;i < n / 2;i++)
    {
        double re = -i * (i / n) * log2(i / n) - (n - i) * ((n - i) / n) * log2((n - i) / n);

        if (fabs(re - ans) < minn)
        {  minn =  fabs(re - ans);
        st = i;
        }
      
          
    }
    cout << st<< endl;
    return 0;
}


posted on 2025-04-02 21:51  Hoshino1  阅读(20)  评论(0)    收藏  举报