Mi informacion de contacto
Correo[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
método codiciosoEs una especie de soluciónProblema de optimizacion Este método siempre considera la estrategia para lograr el resultado global óptimo (o mejor) después del óptimo local (o mejor) en el estado actual. Obviamente, si se adopta una estrategia mejor pero no óptima (la estrategia óptima puede no existir o no es fácil pensar en ella), el resultado global obtenido no puede ser óptimo.Para obtener el resultado óptimo, se requiere que cada estrategia de paso intermedio sea óptima, por lo que se utiliza estrictamente el método codicioso para resolver el problema.optimizar La cuestión requiere una justificación de la estrategia adoptada. La idea general de la prueba es utilizar la prueba por contradicción e inducción matemática, es decir, asumir que la estrategia no puede conducir a la solución óptima, y luego obtener la contradicción mediante una serie de derivaciones para demostrar que la estrategia es óptima. Y finalmente utilizar la inducción matemática para garantizar el óptimo global. Sin embargo, para el uso diario, puede que no sea el momento o no sea fácil probar rigurosamente la estrategia que le viene a la mente (la prueba de la codicia suele ser más difícil que la codicia misma), por lo que, en términos generales, si piensa en una estrategia que parece factible, Y si no puedes dar un contraejemplo, entonces sé lo suficientemente valiente para implementarlo.
Dado un número de números del 0 al 9, puede organizar estos números en cualquier orden, pero debe usarlos todos y hacer que el número objetivo sea lo más pequeño posible (por supuesto, 0 no puede ser el primero). dos 0, dos 1, tres 5 y un 8, el número más pequeño obtenido es 100155858.
Creo que puede ver la estrategia de inmediato: primero seleccione el número más pequeño que no sea 0 del 1 al 9 para generar, y luego genere los números del 0 al 9. La cantidad de veces que se genera cada número es el número restante.
Prueba de estrategia correcta:
El del libro de texto es realmente demasiado abstracto y parece un poco incorrecto. Aquí el propio blogger escribió uno:
- #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];
- }
Lógicamente no es difícil, lo principal es pensar con claridad~
Imagínese si usted fuera el jefe, ¿cómo sería "codicioso"? Obviamente, si sólo necesita vender tantos pasteles de luna con el precio unitario más caro posible dentro de una demanda limitada, ¿no sería posible obtener la mayor facturación? La siguiente es una implementación escrita por el propio blogger, que es diferente a la del libro de texto:
- #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;
- }
Pruebe con cuidado el ciclo whlie de arriba: cuando M no es 0, es decir, todavía hay demanda, venda los pasteles de luna más caros. Vender uno por uno en orden: si la demanda actual es suficiente para vender todos los tipos actuales, el precio total se sumará directamente; si no es suficiente para vender todos los tipos actuales, se venderán tantos como haya; son y se calculan en función del precio unitario ~
Probémoslo con el caso de prueba del libro de texto:
El resultado es 94,50, que es coherente con la respuesta estándar ~
Además, el blogger aquí escribe directamente la clasificación en la función principal, la escribe en una función independiente y luego la llama. Parece que hay un error en el vector de tipo de estructura y la clasificación no se realiza correctamente. motivo, puedes escribirlo en el área de comentarios ~
El tema de la pregunta es el siguiente:
Para este tipo de preguntas, sólo necesitas recordar——Dar prioridad al intervalo con el punto final izquierdo más grande!
Hablemos de por qué hacemos esto, como se muestra en la imagen de arriba: no es difícil de encontrar,Para garantizar tantas opciones como sea posible, cuando un intervalo más largo contiene un intervalo más corto, primero debemos seleccionar el intervalo más corto., esto es facil de entender.
Para la situación anterior, como la superposición de intervalos como 1 y 2, no es difícil encontrar que si selecciona el intervalo 1 con el extremo izquierdo más grande, solo ocupará la posición 9, mientras que si selecciona el intervalo 2, ocupará posición 8. Posición: esto obviamente no está en línea con la idea de que los codiciosos gasten la menor cantidad de dinero posible (gastando menos espacio), por lo que debes elegir lo más a la izquierda posible, para que haya más espacios vacíos. a la derecha ~ como arriba,Podemos ver mediante cálculos manuales que hay como máximo 4 disjuntos.
Código del libro de texto:
- #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;
- }
Sin embargo, a los bloggers todavía no les gustan las matrices originales. Aquí hay una versión de estructura vectorial:
- #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;
- }
La prueba es la siguiente:
En general, el método codicioso es una idea algorítmica que se utiliza para resolver un tipo de problema de optimización y espera derivar el resultado óptimo global a partir de una estrategia óptima local.algoritmo codicioso Los problemas aplicables deben satisfacer las propiedades de la subestructura óptima, es decir, la solución óptima de un problema puede construirse efectivamente a partir de las soluciones óptimas de sus subproblemas. Obviamente no todos los problemas son adecuados para el método codicioso, pero esto no impide que el algoritmo codicioso se convierta en un algoritmo simple, práctico y eficiente ~