uva1025
題意:這個城市有n個車站,每隔一段時間會從所有車站的一遍發出一列列車,有乙個要從第乙個車站出發,目的是在時間t會見車站n 的乙個人,需要換乘,問在不同車站換成所需要等待的最短時間是多少
解法:d(i,j)表示在時刻i,你在j車站所需要等待的最長時間,有三種決策,1. 等一分鐘、2. 搭乘往右開的車、3. 搭乘往左開的車
1 #include2 #include3 #include4using
namespace
std;
5const
int inf = 0x3fffffff;6
int dp[200 + 5][50 + 5];//
在時間t,車站i應該等待的最長時間
7int has_train[205][55][2], t[50 + 5];//
has_train表示在時間t車站i是否有列車
8int d[50 + 5], e[50 + 5];//
往右開的第一班車,往左開的第一班車910
intmain() 26}
27int m2; scanf("
%d", &m2);
28for (int i = 1; i <= m2; i++) 35}
3637
for (int i = 1; i <= n - 1; i++)dp[t][i] =inf;
38 dp[t][n] = 0;39
40for (int i = t - 1; i >= 0; i--)
41for (int j = 1; j <= n; j++)
4849 printf("
case number %d:
", tmp++);
50if (dp[0][1] >= inf) printf("
impossible\n");
51else printf("
%d\n
", dp[0][1
]);52}53
return0;
54 }
uva437
題意:有n種正方體,每種都有無窮多個。要求選一些立方體摞成一根盡量高的柱子,使得每個立方體的地面長寬嚴格小於它下方立方體的地面長寬
解法:見**
1/*2思路:3
因為a和b的值會很大,所以我們不能直接用d(a,b)來表示狀態值;
4所以我們(idx,h)來表示這個狀態,h存放的是立方體的的三條高,知道其中的一條我們就能知道對應的面
5idx表示立方體的編號
6ans就是我們要求的那個結果,即最大高度,狀態轉移就是簡單的拿或者不拿那個立方體7*/
89 #include10 #include11 #include12
using
namespace
std;
13const
int maxn = 30 + 5;14
int n, blocks[maxn][3], d[maxn][3
];15
16void get_dimensions(int* v, int b, int
dim) 21}
2223
int dp(int i,int
j) 34 ans +=blocks[i][j];
35return
ans;36}
3738
intmain()
46 memset(d, 0, sizeof
(d));
47int ans = -1;48
for (int i = 0; i < n; i++) 52}
53 printf("
case %d: maximum height = %d\n
", ++kase, ans);54}
55return0;
56 }
uva116
題意:有乙個m行n列的整數矩陣,從第一列任何乙個位置出發每次往↗↘或者→走一格,最終到達最後一列,要求經過的整數之和最小。整個矩形是環形的,即第一行的上一行是最後一行,最後一行的下一行是第一行。輸出路徑上每列的行號。多解釋輸出字典序最小的
解法:見**
1/*2多階段決策問題,重點是行和列的處理,注意看一下
3還有乙個重點是結點路徑的儲存4*/
5 #include6 #include7 #include8
using
namespace
std;
9const
int inf = 0x3fffffff;10
int a[1010][1010], d[1010][1010], nex[1010][1010
];11
12int
main()
2223
int ans = inf, first = 0;24
for (int j = n - 1; j >= 0; j--) ;//
三個方向
29if (i == 0)row[1] = m - 1;//
上一行是下邊界
30if (i == m - 1)row[2] = 0;//
下一行是上邊界
31 sort(row, row + 3
);32 d[i][j] =inf;
33for (int k = 0; k < 3; k++) 37}
38}39if (j == 0 && d[i][j] < ans) //
更新出發點40}
41}4243 printf("
%d", first + 1
);44
for (int i = nex[first][0], j = 1; j < n; i = nex[i][j], j++) printf("
\n%d\n
", ans);47}
48return0;
49 }
uva12563
題意:有n首歌,剩餘時間為up,每首歌都有乙個時間長度,要求你在剩餘時間內盡可能多的唱歌,同時要求唱的時間盡可能的長
解法:01揹包,雙狀態
1/*2揹包問題的變式,這道題的解法涉及到了乙個dp中核心的解法:狀態
3注意列舉上界up要-14*/
5 #include6 #include7 #include8
using
namespace
std;
9 typedef long
long
ll;10
const
int maxn = 180 * 50 + 5;11
struct
node
16};
17node dp[maxn];
18ll t[maxn];
1920
intmain() ;
34 dp[j] = max(dp[j], tmp);//
選取更優狀態35}
36}3738 printf("
case %d: %d %d\n
", kase++, dp[up].num + 1, dp[up].len + 678
);39}40
return0;
41 }
uva1625
題意:有兩個字串,每次可以選兩個首位的字元將他們加入到新串的尾部,對於每個顏色來說(每個顏色就是每個字元),其跨度l(c)等於最大位置和最小位置之差。找到一種合併方式,使得所有的l(c)總和最小
解法:見**
1/*2非常好的思路題,多多品味3*/
4 #include5 #include6 #include7
using
namespace
std;
8const
int maxn = 5e3 + 5;9
const
int inf = 0x3fffffff;10
intdp[maxn][maxn], cnt[maxn][maxn];
11int bf[100], bs[100], ef[100], es[100
];12
char
f[maxn], s[maxn];
13//
dp[i][j]為從第乙個顏色序列中拿走前i個顏色,從第二個顏色中拿走前j個顏色時合併產生的序列的最小lc之和
14//
cnt[i][j]為分別取走i個顏色和j個顏色時還有多少種顏色已經出現但尚未結束
15//
bf[c]為f串中c字母出現的第乙個位置,es[c]為f串中c字母出現的最後乙個位置
16//
ef同上,只不過對應s串中的情況
1718
intmain()
2728
//處理開始值和終點值,注意處理開始值的時候採用最值的方法可以避免定義first變數
29for (int i = 1; i <= lenf; i++)
34for (int i = 1; i <= lens; i++)
3940
//處理cnt陣列
41for (int i = 0; i <= lenf; i++)
42for (int j = 0; j <= lens; j++)
50if
(j) 56}
5758
for (int i = 0; i <= lenf; i++)
59for (int j = 0; j <= lens; j++)
66 printf("
%d\n
", dp[lenf][lens]);67}
68return0;
69 }
動態規劃(詳細總結 例題)
遞迴到動規的一般轉化方法 遞迴函式 有n個引數,就定義乙個n為的陣列,陣列的下標是遞迴函式引數的取值範圍,陣列元素的值是遞迴函式的返回值,這樣就可以從邊界值開始,逐步填充陣列,相當於計遞迴函式值的逆過程。動態規劃解題的一般思路 1.將原問題分解為子問題 把原問題分解為若干子問題,子問題和原問題形式相...
動態規劃例題
題目描述 有一條很長的數軸,一開始你在0的位置。接下來你要走n步,第i步你可以往右走ai或者bi。問n步之後,0到m的每個位置,能不能走到?輸入格式 第一行,兩個整數n,m。接下來n行,每行兩個整數ai,bi。輸出格式 一行,一共m 1個數,每個數都是0或1表示能否走到,數字之間不用空格隔開。樣例輸...
《動態規劃》 ACM 動態規劃例題詳解
描述 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 圖1 圖1給出了乙個數字三角形。從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到乙個和,你的任務就是找到最大的和。注意 路徑上的每一步只能從乙個數走到下一層上和它最近的左邊的那個數或者右邊的那個數。輸...