演算法上依然是搜尋的流程,但是搜尋到的一些解用動態規劃的那種思想和模式作一些儲存。一般說來,動態規劃總要遍曆所有的狀態,而搜尋可以排除一些無效狀態。 更重要的是搜尋還可以剪枝,可能剪去大量不必要的狀態,因此在空間開銷上往往比動態規劃要低很多。
//最小邊覆蓋=N-二分圖最大匹配 #include<stdio.h>#include<string.h>int map[1000][1000];int mark[1000];int link[1000];int m,n;int find(int k){ int i; for(i=1;i<=m;i++) { if(mark[i]==0&&map[k][i]) { mark[i]=1; if(link[i]==0||find(link[i]
題目大意:Adam和Eve打牌,Eve可以看到Adam的牌,牌的順序先看大小,如果大小一樣,再看C,D,SorH(依次增大),每次出一張牌,大的贏一次,求出Eve能贏得最多次。贏的次數最多即最大匹配數,,簡單,先比較,再建圖。。 #include<stdio.h>#include<string.h>int map[100][100];int link[100];int mark[100];int m;int find(int k){ int i;
首先,讓我們瞭解最小產生樹(Maximal Spanning Tree, MST)問題。Problem: 給定無向帶權圖G=(V,E),其點集為V,邊集為E。要求選出邊集E的一個子集E‘,使得E'能夠讓所有點連通且邊權和最小。由於給定無向圖G,串連G中所有點,且邊集是E的子集的樹稱為G的產生樹(Spanning Tree),而權值最小的產生樹稱為最小產生樹,該問題即是讓我們求出G的最小產生樹。下面給出求解最小產生樹的Prim演算法的表述:(1)取一新點集T = { v0
#include <stdio.h>int pre[2000];int fun(int x) -------------------------------------//找x的根節點((((重要函數))){ int r = x; while(pre[r]!=r)
相關概念歐拉迴路 通過圖中每條邊一次且僅一次,並且過每一頂點的迴路。歐拉路徑 通過圖中每條邊一次且僅一次,並且過每一頂點的通路。歐拉圖 存在歐拉迴路的圖。半歐拉圖 存在歐拉路徑的圖。 無向歐拉圖的判定無向圖存在歐拉迴路的充要條件: 連通且沒有奇度頂點。無向圖存在歐拉路徑的充要條件: 連通且奇度頂點個數為2。 有向歐拉圖的判定有向圖存在歐拉迴路的充要條件: 基圖連通且所有頂點入度等於出度。有向圖存在歐拉路徑的充要條件:
經典的求最長公用子序列(Longest Common Subsequence, LCS) 的一道題,動態規劃妥妥的。要注意的地方是輸入的串可能是空串,所以不要用cin。我的解題代碼如下:#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define MAXN 1005#define max(a,b) ((a)>(b)?(a):(b))//#define
/*第一次用記憶化搜尋,其實並不難,只不過在搜尋的同時記住了在各個座標的權值。在這裡題意是;在一個n*n的矩陣裡,值是權值,在豎直或水平方向上行走1--k步,全只要遞增,不能重複走,到最後使其總權值和最大。說白了就是找一個遞增序列,使其總和值最大。。*/這一題綜合了DFS和DP,很好的一道題。dp[i][j]表示以第i行第j列個網格為起點所能得到的最大值,需要注意的是一次最多走k步必須在一條直線上,這個只需要在普通的深搜上加一層迴圈表示從1步到k步,狀態轉移就是dp[i][j] =
設定一個數組Winner記錄經典約瑟夫問題中的剩餘者即可遞迴解決該問題。註: 約瑟夫問題:有編號為0~n-1的n個人,從0號開始報數1,2,3......報到k的殺死,然後從下一個人開始繼續報數1,2,3......直到剩下最後一個人。約瑟夫想要活下來,問他一開始需要站在幾號位置(編號為幾)。數組Winner也可以只用一個變數代替。我的解題代碼如下:#include <iostream>#include <cstdio>#include
//求最大獨立集,公式: 最大獨立集 = 頂點數 - 最大匹配 / 2;#include<stdio.h>#include<string.h>int map[1000][1000];int mark[1000];int link[1000];int m,n;int find(int k){ int i; for(i=0;i<m;i++) { if(mark[i]==0&&map[k][i]) { mark[i]=1; if(link[i]
二分匹配求重要匹配。先跑一遍二分匹配、求出最大匹配,然後:枚舉每一個匹配,看看刪除它以後進行的二分匹配得到的匹配數目還能不能等於之前的最大的匹配不能的話就是所求重要點。 #include<stdio.h>#include<string.h>int map[2006][2006];int mark[2006],link[2006];int n,m;int find(int k){int
動態規劃題。對於1,5,10,25,50五種幣值的硬幣,編號為0~4,存入數組cent中。數組iWay的元素iWay[k][i]表示僅使用0~i的硬幣湊出k分錢的方法數,按是否使用編號為i的硬幣分類,可得到狀態轉移方程iWay[k][i]=iWay[k][i-1]+iWay[k-cent[i]][i]。一個最佳化的方法:分析可知取15,16,17,18,19分錢的方法數是相同的,因為它們的差距只在於1分的硬幣數目。故iWay[k][i]=iWay[k/5*5][i]。這個式子可以稍微節省程式啟動
//解題思路:記錄好訪問過點的狀態,再去訪問其他的點。//廣搜題: //要理解搜尋的過程。。#include<stdio.h>#include<string.h>int dir[4][2]={1,0, -1,0, 0,1, 0,-1};char map[26][26];int n,m,sum;void dfs(int x,int y){ int x1,y1,i; map[x][y]='#';//不能少。。 for(i=0;i<4;i++) { x1=x+
動態規劃題。切棍子,類似矩陣連乘問題(Matrix Multiplication problem)。當時我先寫了一個比較簡潔的遞迴代碼,但是逾時了。。。逾時代碼如下,雖然逾時,但可以很好的體現出狀態轉移:#define INF 50000int c[50];int dp(int left, int right, int cleft, int cright){if(cleft==cright) return 0;int min = INF;int tmp;for(int i=cleft;
用優先隊列確定最短時間,並用數組 記錄路線。。BFS:如果能找到路徑, 要輸出最短時間內的路徑資訊.為了方便輸出路徑, 從終點開始BFS, 搜尋最短的路徑,每個位置元素中, 記錄前一個位置的資訊, 則能輸出從起點(0, 0) 到 (終點)的最短路徑.最短路徑:從 out 往周圍搜尋其他位置時, 當搜到一點 in;此時就判斷:(0, 0) -> cur -> next這樣加入位置 cur 後是否會縮短 (0, 0) -> next
題意: 這題是一道簡單的物理題,實際上只要一個拋物線的公式就可以了,一共有3種鳥,各有不同的特性:紅鳥的軌跡是一條拋物線;黃鳥的前期軌跡是一條拋物線,在t時,黃鳥的Vx,Vy翻倍;藍鳥的前期軌跡是一條拋物線,在t時,可以分裂成3隻小藍鳥,每隻的軌跡都是拋物線。分析:說來說去,其實都是求拋物線的,因此只要有一個函數用來計算,那麼做起來會方便的多。 #include"stdio.h"#include"string.h"#include"math.h"double fun(double
題目大意就是,有一個圖,上面有一些頂點,代表一些城市,在某些時刻, 某個城市裡會有人需要禮物,
本題是一個貪心題,關鍵在于思考如何排序才好;這裡應該用最多多餘時間來排序,即:s[i].x=s[i].v-s[i].d-t;在這裡需要明白的幾點是:每行在開打之前都需要t時間來種植植物;所以排序要按上面的進行也就很好解釋了;此題最好用結構體來寫,四個兩都要在其中,因為排完序之後,v和d的順序,也要按排完後比較;在此,再比較判斷時,t每次都要增加t,如果打死需要的時間和在此前總種植的時間之和小於度過總時間,則會吃到。。#include"stdio.h"#include"algorithm"usin
簡單數論題,注意使用long long類型,最好直接打表,因為只要輸出十行。我的解題代碼如下://#include <iostream>#include <cstdio>/*#include <cstring>#include <cmath>#include <cstdlib>#include <string>#include <algorithm>using namespace std;*/int main()
當字串長度為2時:直接類比即可(最多26次)。當字串長度大於2時:1. 定義字串的奇偶性為該字串所有字元之和的奇偶性。2. 因為每次變化操作字串的字元和共增加了2,所以當字串的奇偶性不同時答案一定為N O。3. 當字串的奇偶性相同時可證明答案一定為YES;可以證明;對於任意3個位置的字元(x1 , x2 , x3 ),可進行如下變化:(x1 , x2 , x3 ) → (x1 , x3 + 1, x2 + 1) → (x2 + 2, x3 + 1, x1 + 1) → (x2 +2, x1 +