моя контактная информация
Почтамезофия@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
жадный методЭто своего рода решениеПроблема оптимизации Этот метод всегда рассматривает стратегию достижения оптимального (или лучшего) глобального результата после локального оптимального (или лучшего) в текущем состоянии. Очевидно, что если будет принята лучшая, но не оптимальная стратегия (оптимальная стратегия может не существовать или ее нелегко придумать), полученный глобальный результат не может быть оптимальным.Для получения оптимального результата каждая стратегия промежуточного шага должна быть оптимальной, поэтому для решения задачи строго используется жадный метод.оптимизировать Вопрос требует обоснования принятой стратегии. Общая идея доказательства состоит в том, чтобы использовать доказательство от противного и математическую индукцию, то есть предположить, что стратегия не может привести к оптимальному решению, а затем получить противоречие посредством ряда выводов, чтобы доказать, что стратегия оптимальна. и, наконец, использовать математическую индукцию, чтобы обеспечить глобальный оптимум. Однако для повседневного использования может оказаться невозможным и непростым строго доказать стратегию, которая приходит на ум (доказательство жадности часто сложнее, чем сама жадность), поэтому, вообще говоря, если вы думаете о стратегии, которая кажется осуществимой, А если вы не можете привести контрпример, то наберитесь смелости его реализовать.
Учитывая количество чисел от 0 до 9, вы можете расположить эти числа в любом порядке, но вы должны использовать их все и сделать целевое число как можно меньшим (конечно, 0 не может быть первым). два 0, две 1, три 5 и An 8, наименьшее полученное число — 100155858.
Я думаю, вы сразу можете увидеть стратегию: сначала выберите для вывода наименьшее число от 1 до 9, отличное от 0, а затем выведите числа от 0 до 9. Количество раз, когда выводится каждое число, равно его оставшемуся числу.
Доказательство правильной стратегии:
Тот, что в учебнике, действительно слишком абстрактен и кажется немного неправильным. Вот блоггер сам написал:
- #include <cstdio>
- #include <vector>
- #include <iostream>
- #include <algorithm>
- using namespace std;
-
- int main() {
- vector<int> V;
- for(int i=1;i<=10;i++)
- {
- int temp=0;
- cin>>temp;
- V.push_back(temp);
- }
- sort(V.begin(),V.end()); //直接排成升序
- int flag=0; //标记
- for(int i=0;i<=9;i++)
- if(V[i]!=0)
- {
- int temp=V[i];
- V[i]=V[0];
- V[0]=temp;
- flag=i;//保存第一个不为0的位置
- break;
- }
- for(int i=flag+1;i<=9;i++) //找更小的头,直接从flag下一位开始即可,节省时间~
- if(V[i]<V[0]&&V[i]!=0)
- {
- int temp=V[i];
- V[i]=V[0];
- V[0]=temp;
- }
- for(int i=0;i<=9;i++)
- cout<<V[i];
- }
Логически это не сложно, главное ясно мыслить~
Представьте себе, если бы вы были начальником, как бы вы были «жадными»? Очевидно, что если вам нужно продать как можно больше лунных пирожных по самой дорогой цене за единицу в рамках ограниченного спроса, разве невозможно будет получить наибольший оборот? Ниже приведена реализация, написанная самим блоггером и отличающаяся от той, что приведена в учебнике:
- #include <cstdio>
- #include <vector>
- #include <iostream>
- #include <algorithm>
- using namespace std;
-
- struct mooncake{
- double num; //总数
- double income; //总收入
- double price; //单价,需要自己计算
- };
-
- int main() {
- int N,M;
- cin>>N>>M;
- vector<mooncake> V;
- for(int i=1;i<=N;i++)
- {
- mooncake temp;
- V.push_back(temp);
- }
- cout<<"请输入数量:"<<endl;
- for(int i=1;i<=N;i++)
- {
- double num=0;
- cin>>num;
- V[i-1].num=num;
- }
- cout<<"请输入总价:"<<endl;
- for(int i=1;i<=N;i++)
- {
- double income=0;
- cin>>income;
- V[i-1].income=income;
- }
- for(int i=0;i<=N-1;i++)
- V[i].price=V[i].income/V[i].num; //计算单价
- //按单价降序排列!保证贵的尽可能多卖
-
- for(int i=0;i<=V.size()-1;i++)
- {
- for(int j=i;j<=V.size()-1;j++)
- if(V[j].price>V[i].price)
- {
- mooncake temp;
- temp=V[j];
- V[j]=V[i];
- V[i]=temp;
- }
- }
- for(int i=0;i<=V.size()-1;i++)
- cout<<"单价第"<<(i+1)<<"高的值为:"<<V[i].income<<" "<<V[i].price<<" "<<V[i].num<<endl;
-
-
- for(int i=0;i<=N-1;i++)
- cout<<V[i].num<<endl;
- int j=0; //使用的下标
- double count=0; //总利润
- while(M>0) //当还有需求量时
- {
- double doubt=0;
- doubt=M-V[j].num; //用M减去当前类型的额总量
- if(doubt>=0)//减了以后M还有剩余
- {
- M-=V[j].num;//当前种类全部卖出
- count+=V[j].income;//直接总价相加
- j++;
- cout<<V[j].num;
- }
- else if(doubt<0) //不够减这么多
- {
- count+=V[j].price*M;//剩余部分按照单价计算
- break;
- }
- }
- cout<<"最高利润值为:"<<count<<endl;
- return 0;
- }
Внимательно посмотрите на цикл выше: когда M не равно 0 — то есть спрос все еще есть, продавайте самые дорогие лунные пирожные. Продавайте по одному по порядку: Если текущего спроса достаточно, чтобы распродать все текущие типы, общая цена будет добавлена напрямую, если недостаточно, чтобы распродать все текущие типы, то продайте столько, сколько есть; являются и рассчитываются на основе цены за единицу ~
Проверим это на тестовом примере из учебника:
Результат — 94,50, что соответствует стандартному ответу~
Кроме того, блоггер здесь напрямую записывает сортировку в основную функцию, записывает ее в независимую функцию и затем вызывает ее. Похоже, в векторе типа структуры есть ошибка, и сортировка не удалась, если вы знаете. причина, вы можете написать это в комментариях~
Суть вопроса следующая:
Для такого типа вопросов вам просто нужно запомнить:Отдайте приоритет интервалу с большей левой конечной точкой.!
Давайте поговорим о том, почему мы это делаем, как показано на картинке выше: найти не сложно,Чтобы обеспечить как можно больше вариантов выбора, когда более длинный интервал содержит более короткий интервал, мы должны сначала выбрать самый короткий интервал., это легко понять.
В приведенной выше ситуации, например, при перекрывающихся интервалах, таких как 1 и 2, нетрудно обнаружить, что если вы выберете интервал 1 с наибольшей левой конечной точкой, он займет только позицию 9, а если вы выберете интервал 2, он займет позиция 8. Позиция - Это явно не соответствует идее жадной траты как можно меньше денег (затрачивая меньше места), поэтому следует выбирать как можно левее, чтобы было больше пустых мест справа ~ как указано выше,Путем ручного расчета мы видим, что существует не более 4 непересекающихся.
Код из учебника:
- #include <cstdio>
- #include <algorithm>
- using namespace std;
-
- const int maxn=110;
- struct Inteval{
- int x,y; //开区间左右端点
- }I[maxn];
-
- bool cmp(Inteval a,Inteval b)
- {
- if(a.x!=b.x)
- return a.x>b.x; //左端点从大到小排序
- else
- return a.y<b.y; //左端点相同的按右端点从小到大排序
- }
-
- int main() {
- int n;
- while(scanf("%d",&n,n!=0))
- {
- for(int i=0;i<n;i++)
- scanf("%d%d",&I[i].x,&I[i].y);
- sort(I,I+n,cmp); //排序区间
- int ans=1,lastX=I[0].x;
- //ans记录总数,lastX记录上一个被选择的区间的左端点
- for(int i=1;i<n;i++)
- {
- if(I[i].y<=lastX) //如果该区间右端点在lastX左边
- {
- lastX=I[i].x; //以I[i]作为新选中的区间
- ans++; //不相交的区间个数+1
- }
- }
- printf("%dn",ans);
- }
- return 0;
- }
Однако блоггеры до сих пор не любят оригинальные массивы. Вот вариант векторной структуры:
- #include <iostream>
- #include <vector>
- #include <algorithm>
- using namespace std;
-
- struct section{
- int x=0;
- int y=0;
- //x和y分别为左右端点
- };
-
-
- int main() {
- int n=0;
- vector<section> V;
- cin>>n;
- for(int i=1;i<=n;i++) //读入数据
- {
- section temp;
- int x=0,y=0;
- cin>>x>>y;
- if(x>y) //防止左端点大于右端点
- {
- int temp1=x;
- x=y;
- y=temp1;
- }
- else if(x==y) //若左右端点相同
- {
- i-=1; //则当前输入 不算
- cout<<"不可以输入相同的左右端点!"<<endl;
- continue; //舍弃数据,本次循环作废~
- }
- temp.x=x;
- temp.y=y;
- V.push_back(temp);
- }
- //按要求排序区间优先级
- for(int i=0;i<=V.size()-1;i++)
- {
- for(int j=i+1;j<=V.size()-1;j++)
- {
- if(V[j].x>V[i].x) //左端点越大越靠前
- {
- section temp=V[j];
- V[j]=V[i];
- V[i]=temp;
- }
- else if(V[j].x==V[i].x&&V[j].y<V[i].y) //左端点相同的话,右端点小的优先
- {
- section temp=V[j];
- V[j]=V[i];
- V[i]=temp;
- }
- }
- }
- cout<<"顺序如下:"<<endl;
- for(int i=0;i<=V.size()-1;i++)
- cout<<V[i].x<<"~"<<V[i].y<<endl;
- int count=1,lastX=V[0].x;
- //count用来统计总数,lastX是上一个符合条件的区间的左端点
-
- for(int i=1;i<=V.size()-1;i++)//直接从第二个区间开始
- {
- if(V[i].y<lastX) //如果当前区间的右端点不和上一个左端点相加,满足题意
- {
- lastX=V[i].x;
- count++;
- }
- }
- cout<<count<<endl;
- return 0;
- }
Тест заключается в следующем:
В общем, жадный метод — это алгоритмическая идея, используемая для решения определенного типа задач оптимизации и позволяющая получить глобальный оптимальный результат из локальной оптимальной стратегии.жадный алгоритм Применимые проблемы должны удовлетворять свойствам оптимальной подструктуры, то есть оптимальное решение проблемы может быть эффективно построено из оптимальных решений ее подзадач. Очевидно, что не все задачи подходят для жадного метода, но это не мешает жадному алгоритму стать простым, практичным и эффективным алгоритмом~