主頁 > 軟體設計 > 演算法學習:動態規劃

演算法學習:動態規劃

2021-12-09 09:25:43 軟體設計

基礎DP(狀態轉移和遞推)
1.硬幣問題
有多個不同面值的硬幣,輸入最少硬幣組合,
這里要是用貪心,所得組合和實際可能不符合,
利用dp法,代碼如下:

#include<bits/stdc++.h>
using namespace std;
const int MONEY=1001;                  //定義最大金額
const int VALUE=5;                     //5種硬幣
int type[VALUE]={1,5,10,25,50};    //5種面值
int Min[MONEY];               //每個金額對應最少的硬幣數量
void solve(){
    for(int k=0;k<MONEY;k++)         //初始值為無窮大
       Min[k]=INT_MAX;
    Min[0]=0;
    for(int j=0;j<VALUE;j++)
        for(int i=type[j];i<MONEY;i++)
            Min[i]=min(Min[i],Min[i-type[j]]+1);    //遞推式
}
int main(){
    int s;
    solve();                    //提前計算出所有金額對應的最少硬幣數量,打表
    while(cin>>s)
        cout<<Min[s]<<endl;
    return 0;
}

拓展問題:要求列印最少硬幣的組合,
解決方法:增加一個記錄表Min_path[i],記錄金額i需要的最后一個硬幣,利用Min_path[]逐步倒推,就能得到所有的硬幣,
如:
Min_path[6]=5:最后一個硬幣是5元的;
Min_path[6-5]=1:1元硬幣;
Min_path[1-1]=0:結束;
代碼如下:

#include<bits/stdc++.h>
using namespace std;
const int MONEY=1001;              //定義最大金額
const int VALUE=5;                 //5種硬幣
int type[VALUE]={1,5,10,25,50};  //5種面值
int Min[MONEY];                       //每個金額對應最少的硬幣數量
int Min_path[MONEY]={0};            //記錄最小硬幣的路徑
void solve(){
    for(int k=0;k<MONEY;k++)
        Min[k]=INT_MAX;
    Min[0]=0;
    for(int j=0;j<VALUE;j++)
        for(int i=type[j];i<MONEY;i++)
            if(Min[i]>Min[i-type[j]]+1){
               Min_path[i]=type[j];   //在每個金額上記錄路徑,即某個硬幣的面值
               Min[i]=Min[i-type[j]]+1;  //遞推式
            }
}
void print_ans(int *Min_path,int s){      //列印硬幣組合
    while(s){
        cout<<Min_path[s]<<" ";
        s=s-Min_path[s];
    }
}
int main(){
    int s;
    solve();
    while(cin>>s){
        cout<<Min[s]<<endl; 	  	 //輸出最少硬幣個數
        print_ans(Min_path,s); 		 //列印硬幣組合
    }
    return 0;
}

拓展問題:硬幣組合方案有幾種
代碼如下:

#include<bits/stdc++.h>
using namespace std;
const int COIN=101;                   //題目要求不超過100個硬幣
const int MONEY=251;                  //題目給定的錢數不超過250
int dp[MONEY][COIN]={0};              // DP轉移矩陣
int type[5]={1,5,10,25,50};      //5種面值
void solve(){                             // DP
    dp[0][0]=1;
    for(int i=0;i<5;i++)
        for(int j=1;j<COIN;j++)
            for(int k=type[i];k<MONEY;k++)
                dp[k][j]+=dp[k-type[i]][j-1];
}
int main(){
    int s;
    int ans[MONEY]={0};
    solve();                          //用DP計算完整的轉移矩陣
    for(int i=0;i<MONEY;i++)   //對每個金額,計算有多少種組合方案,打表
        for(int j=0;j<COIN;j++)  //從0開始,注意 dp[0][0]=1
            ans[i]+=dp[i][j];
    while(cin>>s)
        cout<<ans[s]<<endl;
    return 0;
}

2.0/1背包問題
用dp[i][j]陣列,表示將前i個物品放入容量為j的背包中產生的價值,
有 N 件物品和一個容量是 V 的背包,每件物品只能使用一次,

第 i 件物品的體積是 vi,價值是 wi,

求解將哪些物品裝入背包,可使這些物品的總體積不超過背包容量,且總價值最大,
輸出最大價值,

輸入格式
第一行兩個整數,N,V,用空格隔開,分別表示物品數量和背包容積,

接下來有 N 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值,

輸出格式
輸出一個整數,表示最大價值,

資料范圍
0<N,V≤1000
0<vi,wi≤1000
輸入樣例
4 5
1 2
2 4
3 4
4 5
輸出樣例:
8

代碼如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
typedef struct{
    int v;
    int w;
}Node;
int dp[1005][1005];
int main()
{
    int N,V;
    scanf("%d%d",&N,&V);
    Node* node=new Node[N+1];
    for(int i=1;i<=N;i++)
        scanf("%d%d",&node[i].v,&node[i].w);
    for(int i=1;i<=N;i++){
        for(int j=1;j<=V;j++){
            if(node[i].v>j)
                dp[i][j]=dp[i-1][j];
            else
                dp[i][j]=max(dp[i-1][j-node[i].v]+node[i].w,dp[i-1][j]);
        }
    }
    printf("%d\n",dp[N][V]);
}

動態規劃法的設計思想:
如果各個子問題的不是獨立的,如果能夠保存已經解決的子問題的答案,而在需要的時候再找出已求得的答案,這樣就可以避免大量的重復計算,‘
基本思路是,用一個表記錄所有已解決的子問題的答案,不管該問題以后是否被用到,只要它被計算過,就將其結果填入表中,

3.完全背包問題
有 N 種物品和一個容量是 V 的背包,每種物品都有無限件可用,

第 i 種物品的體積是 vi,價值是 wi,

求解將哪些物品裝入背包,可使這些物品的總體積不超過背包容量,且總價值最大,
輸出最大價值,

輸入格式
第一行兩個整數,N,V,用空格隔開,分別表示物品種數和背包容積,

接下來有 N 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 種物品的體積和價值,

輸出格式
輸出一個整數,表示最大價值,

資料范圍
0<N,V≤1000
0<vi,wi≤1000
輸入樣例
4 5
1 2
2 4
3 4
4 5
輸出樣例:
10

直接上一段代碼:

#include<bits/stdc++.h>
using namespace std;
typedef struct{
    int v,w;
}Node;
int dp[1005][1005];
int main(){
    int N,V;
    scanf("%d%d",&N,&V);
    Node* node=new Node[N+1];
    for(int i=1;i<=N;i++)scanf("%d%d",&node[i].v,&node[i].w);
    for(int i=1;i<=N;i++)
        for(int j=0;j<=V;j++)
            for(int k=0;k*node[i].v<=j;k++)
                dp[i][j]=max(dp[i][j],dp[i-1][j-k*node[i].v]+k*node[i].w);
    printf("%d\n",dp[N][V]);
}

這個代碼和0/1背包有些相似,這里求解dp陣列時,用3個for回圈,遍歷前i個物品在背包容量為j的背包中產生的最大價值,方法為:
取定第i個物品,直接回圈確定從0最大的k個i物品能產生的最大價值,可以理解為:裝入k個i物品,相當于將前i-1個物品選定最大價值裝入容量為j-knode[i].v的包中,那么這樣做的價值為dp[i-1][j-knode[i].v]+k*node[i].w,和原始的dp[i][j]不斷比較,逐漸選擇出最大價值的dp[i][j]

理解完全背包問題時,可以和0/1背包做比較,加深理解,
但是這題如果是這樣做的話,顯得太過暴力,事實上,這樣提交上去是會給超時的!
那么接下來,我們需要對這個問題做個優化:

首先了解dp更新時的內部關系:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v]+w,dp[i-1][j-2v]+2w+dp[i-1][j-3v]+3w+…)
遞推下去
dp[i][j - v] = max ( ,dp[i-1][j-v],dp[i-1][j-2v]+w+dp[i-1][j-3v]+2*w);
遞推得出:dp[i][j]=max(dp[i-1][j],dp[i][j-v]+w);

有了上面的遞推關系式,可以將代碼優化為:

for(int i=1;i<=N;i++)
	for(int j=0;j<=V;j++)
		if(j-node[i].v>=0)
			dp[i][j]=max(dp[i][j],dp[i][j-node[i].v]+ndoe[i].w);
		else dp[i][j]=dp[i-1][j];

至此,完全背包優化代碼如下:

#include<bits/stdc++.h>
using namespace std;
typedef struct{
    int v,w;
}Node;
int dp[1005][1005];
int main(){
    int N,V;
    scanf("%d%d",&N,&V);
    Node* node=new Node[N+1];
    for(int i=1;i<=N;i++)scanf("%d%d",&node[i].v,&node[i].w);
    for(int i=1;i<=N;i++)
        for(int j=0;j<=V;j++)
            if(j-node[i].v>=0)
                dp[i][j]=max(dp[i-1][j],dp[i][j-node[i].v]+node[i].w);
            else dp[i][j]=dp[i-1][j];
    printf("%d\n",dp[N][V]);
}

4.最長公共子序列
給定兩個長度分別為 N 和 M 的字串 A 和 B,求既是 A 的子序列又是 B 的子序列的字串長度最長是多少,

輸入格式
第一行包含兩個整數 N 和 M,

第二行包含一個長度為 N 的字串,表示字串 A,

第三行包含一個長度為 M 的字串,表示字串 B,

字串均由小寫字母構成,

輸出格式
輸出一個整數,表示最大長度,

資料范圍
1≤N,M≤1000
輸入樣例:
4 5
acbd
abedc
分析:

分別遍歷兩個序列,
若Ai=Bj,求最長公共子序列的長度,則只需要求A的前i-1個和B的前j-1個公共子序列的長度,然后再加1即可,即:
dp[i][j]=dp[i-1][j-1]+1;
若Ai!=Bj,求最長公共子序列的長度,只有兩種可能,一種是A的前i個和B的前j-1的最長公共子序列長度,另一種是A的前i-1個和B的前j個的最長公共子序列長度,即:
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

知曉了動態方程,代碼就能很容易寫出:

#include<bits/stdc++.h>
using namespace std;
int num[1005][1005];
int main(){
    int n,m;
    string a,b;
    scanf("%d%d",&n,&m);
    cin>>a;
    cin>>b;
    memset(num,0,sizeof(num));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i-1]==b[j-1])num[i][j]=num[i-1][j-1]+1;
            else
                num[i][j]=max(num[i-1][j],num[i][j-1]);
        }
    }
    printf("%d\n",num[n][m]);
}

5.最長遞增子序列(LIS問題)
給定一個長度為 N 的數列,求數值嚴格單調遞增的子序列的長度最長是多少,

輸入格式
第一行包含整數 N,

第二行包含 N 個整數,表示完整序列,

輸出格式
輸出一個整數,表示最大長度,

資料范圍
1≤N≤1000,
?109≤數列中的數≤109
輸入樣例:
7
3 1 2 1 8 5 6
輸出樣例:
4

分析:

用雙重回圈,第一層回圈遍歷這個數列,第二個回圈借助在第一層回圈遍歷到的數列下標i,再次遍歷陣列從0到i-1,如果遍歷的數列num[i]>num[j],那么最長遞增長度要么是以遍歷到j的最長長度+1,要么就是原先計算出來的最長長度(一開始每個第一層回圈開始時元素的最長遞增長度都設定為1),接著再用一個元素記錄最長的長度即可,
這樣做的復雜度為O(n^2),

代碼如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N;
    scanf("%d",&N);
    int* num=new int[N];
    int* dp=new int[N];
    int len=1;
    for(int i=0;i<N;i++)scanf("%d",&num[i]);
    for(int i=0;i<N;i++){
        dp[i]=1;
        for(int j=0;j<i;j++)
            if(num[i]>num[j])
                dp[i]=max(dp[i],dp[j]+1);
        len=max(len,dp[i]);
    }
    printf("%d\n",len);
}

該題可以用更高效的演算法,利用dp以及二分法,dp表示規則為:
dp[i]表示長度為i的遞增子序列中最后一個元素最小的值,
狀態計算:對所有num[i],如果大于dp[cnt-1],(下標從0開始,cnt長度的最長上升子序列,末尾最小的數字),那就cnt++,使得最長上升序列長度+1,當前末尾最小元素為num[i];若num[i]小于等于dp[cnt-1],說明不會更新當前的長度,但之前末尾的最小元素要發生變化,找到第一個 大于或等于 (這里不能是大于) num[i],更新以那時候末尾的最小元素,
dp[i]一定是一個單調遞增的陣列,所以可以用二分法查找,復雜度為O(nlogn)

代碼如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N,cnt=0;
    scanf("%d",&N);
    int* num=new int[N];
    int* dp=new int[N];
    for(int i=0;i<N;i++)scanf("%d",&num[i]);
    dp[cnt++]=num[0];
    for(int i=1;i<N;i++){
        if(num[i]>dp[cnt-1])dp[cnt++]=num[i];
        else{
            int l=0,r=cnt-1;
            while(l<r){
                int mid=(l+r)>>1;
                if(dp[mid]>=num[i])r=mid;
                else l=mid+1;
            }
            dp[r]=num[i];
        }
    }
    printf("%d\n",cnt);
}

遞推和記憶化搜索
前面dp的狀態轉移,都是用遞推的方法,
有另一種方法,邏輯上的理解更加直接,就是“遞回+記憶化搜索”實作遞回,
經典題:The Triangle
給定一個n層的三角形數塔,從頂部第一個數往下走,每層經過一個數字,直到最底層,只能走斜下方的左邊一個數或右邊一個數,問所有可能走到的路徑最大的數字和為多少?

分析:

本題如果按“從頂往下”的計算方法,有2^n個路徑,導致TLE,
可以使用遞推,即從底往上計算,對數塔上的每個點記錄狀態,dp[i][j]記錄從第i層第j個數開始往下走的數字和,每個節點算一次,復雜度O(n^2),
dp的另一種寫法:遞回+記憶化搜索:
首先,寫遞回程式,暴力搜索所有2^n個路徑

int dfs(int i,int j){
	if(i==n)
		return a[i][j];//遞回邊界,到達最后一行,回傳
	return dp[i][j]=max(dfs(i+1,j),dfs(i+1,j+1))+a[i][j];
	//從左邊走上來,或者從右邊走上來,取其中大的,
}

遞回的優化:記憶化搜索
遞回時,可以避免大量的重復計算,如下圖:

在這里插入圖片描述

觀察第3層的中間數“1”,從第二層的“3”往下走會經過它,從第二層的“8”往下走也會經過它,那么就重復計算了1開始的遞回,只要能避免這些重復計算,就能優化,

int dfs(int i,int j){
	if(i==n)
		return a[i][j];
	if(dp[i][j]>=0)return dp[i][j];//記憶
	return dp[i][j]=max(dfs(i+1,j),dfs(i+1,j+1))+a[i][j];	
}

區間dp
步驟:(1)先在小區間進行dp得到最優解;
(2)合并小區間的最優解,求大區間的最優解
經典題1:石子合并
設有 N 堆石子排成一排,其編號為 1,2,3,…,N,

每堆石子有一定的質量,可以用一個整數來描述,現在要將這 N 堆石子合并成為一堆,

每次只能合并相鄰的兩堆,合并的代價為這兩堆石子的質量之和,合并后與這兩堆石子相鄰的石子將和新堆相鄰,合并時由于選擇的順序不同,合并的總代價也不相同,

例如有 4 堆石子分別為 1 3 5 2, 我們可以先合并 1、2 堆,代價為 4,得到 4 5 2, 又合并 1,2 堆,代價為 9,得到 9 2 ,再合并得到 11,總代價為 4+9+11=24;

如果第二步是先合并 2,3 堆,則代價為 7,得到 4 7,最后一次合并代價為 11,總代價為 4+7+11=22,

問題是:找出一種合理的方法,使總的代價最小,輸出最小代價,

輸入格式
第一行一個數 N 表示石子的堆數 N,

第二行 N 個數,表示每堆石子的質量(均不超過 1000),

輸出格式
輸出一個整數,表示最小代價,

資料范圍
1≤N≤300
輸入樣例:
4
1 3 5 2
輸出樣例:
22

分析:

核心:最后一次合并一定是左邊連續的一部分和右邊連續的一部分進行合并
狀態表示:dp[i][j]表示把第i堆到第j堆合并的方案集合中的最小代價,

區間dp的常用模板:
第一維列舉區間長度,從1到n-1;第二維列舉起點i,從i到n-len;則終點就為j=i+len(自動生成)

代碼如下:

#include<bits/stdc++.h>
using namespace std;
const int INF=1<<30;
const int N=305;
int sum[N],n;
int Minval(){
    int dp[N][N];
    for(int i=1;i<=n;i++)
        dp[i][i]=0;
    for(int len=1;len<n;len++)       //len是i和j之間的距離
        for(int i=1;i<=n-len;i++){  //從第i堆開始
            int j=i+len;               //自動得到右端點
            dp[i][j]=INF;
            for(int k=i;k<j;k++)         //i和j之間,用k進行分割
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
        }
    return dp[1][n];
}
int main(){
    cin>>n;
    sum[0]=0;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        sum[i]=sum[i-1]+x;       //sum[i,j]的值等于 sum[j]-sum[i-1]
    }
    cout<<Minval()<<endl;
    return 0;
}

經典題2:回文串(暫略)

樹形dp

在樹這種資料結構上進行的dp:給出一棵樹,要求以最少的代價(或取得最大收益)完成給定的操作,
在樹上做動態規劃很適合,因為樹本身有“子結構”性質,具有遞回性,符合dp的性質,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/377152.html

標籤:其他

上一篇:基于java Springboot+Vue+shiro前后端分離疫情防疫管理系統設計和實作2.0

下一篇:回文串問題一網打盡

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more