刷题中的逆向思维~

当我们遇到一道算法题,有时候从正面解决问题很困难,或者根本不能解决问题,那么这时候既可以从反面来思考;

只是通过文字说明是不行的,来看两道例题,让我们锻炼一下自己的思维;

T1:滑雪场设计

题目

刷题中的逆向思维~_第1张图片

刷题中的逆向思维~_第2张图片

 

思路

开始准备用贪心来做,后来发现山峰的高度变换后,可能导致一系列问题,比如最高峰和最低峰变成了其他山峰,因为有后效性,所以无法直接使用贪心。

换一种思路:

修改后,任意两个山峰之间距离不大于17;也就是最大值与最小值的差为17;

每座山的初始高度都在 0∼100 之间,如果修改后最低的山峰为0的话,最高的山峰就是17,如果修改后最低的山峰为50的话,最高的山峰就是57;

修改后,最低的山峰的范围为0~83,对应最高的山峰为17~100;

因此我们只需要枚举这83种情况,比最低峰小的话就加上,比最高峰大的话就减去;

代码

#include
#include
#include
#include

using namespace std;
const int N = 1010;
int n;
int h[N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>h[i]; //输入
    int ans=1e8; 
    //枚举83种情况,比最低峰小的话就加上,比最高峰大的话就减去;
    for(int i=0;i<=83;i++) //枚举83种情况
    {
        int res=0;
        for(int j=1;j<=n;j++)
        {
            if(h[j]i+17) res+=pow(h[j]-i-17,2); //大于最高峰
        }
        ans=min(res,ans); //找到最小的差值
    }
    cout<

T2:里程表

题目

刷题中的逆向思维~_第3张图片

刷题中的逆向思维~_第4张图片

 

思路

一看这道题数据范围大的快上天了,哪怕把所有的数字循环一次都会TLE。

并不难,就是在于逆向思维。

我们就可以换一个角度想,因为“有趣的数”并不多,所以我们可以先枚举出每一个“有趣的数”,最后判断区间(x,y)(x,y)之间有几个“有趣的数”即可。

枚举的层次:

数字长度->构造一个各位全部相同的数字->新的数字k,判重并改字符->统计答案

代码

//预处理出来所有的有趣的数字
#include
#include
#include

using namespace std;
long long x,y,ans; //不开long long见祖宗
int main()
{
    cin>>x>>y;
    for(int i=3;i<=17;i++) //i表示数字的长度
    {
        for(int j=0;j<=9;j++) //相同的数字
        {
            //构造一个字符串strstr,长度为i,并且把每一位都赋值为j这个数
            //但是在这里要转化为字符形式
            string str(i, '0' +j);
            for(int k=0;k<=9;k++) //不同的数字
            {
                if(k==j) continue; //判重
                for(int p=0;p=x&&t<=y) ans++;
                    str[p]='0'+j; //还原现场,进行下一次循环
                }
            }
        }
    }
    cout<

你可能感兴趣的:(算法)