題目描述:
阿福是一名經驗豐富的大盜。趁著月黑風高,阿福打算今晚洗劫一條街上的店鋪。
這條街上一共有 n家店鋪,每家店中都有一些現金。
阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街上的報警系統才會啟動,然後警察就會蜂擁而至。
作為一向謹慎作案的大盜,阿福不願意冒著被警察追捕的風險行竊。
他想知道,在不驚動警察的情況下,他今晚最多可以得到多少現金?
輸入格式
輸入的第一行是乙個整數 t,表示一共有 t組資料。
接下來的每組資料,第一行是乙個整數 n,表示一共有 n家店鋪。
第二行是 n個被空格分開的正整數,表示每一家店鋪中的現金數量。
每家店鋪中的現金數量均不超過1000。
輸出格式
對於每組資料,輸出一行。
該行包含乙個整數,表示阿福在不驚動警察的情況下可以得到的現金數量。
資料範圍
1≤t≤50,
1≤n≤10^5
輸入樣例:
2
31 8 2
410 7 6 14
輸出樣例:
8
24
樣例解釋
對於第一組樣例,阿福選擇第2家店鋪行竊,獲得的現金數量為8。
對於第二組樣例,阿福選擇第1和4家店鋪行竊,獲得的現金數量為10+14=24。
分析:方法一:線性dp
作為乙個典型的線性dp問題,本題可以用線性dp的解法來解決。狀態表示f[i]表示在前i家店鋪中能夠獲得的最多的現金。如果第i家店鋪不洗劫,則獲得的現金與在前i-1家店鋪獲得的最大現金一致,即f[i] = f[i-1];如果第i家店鋪洗劫,則第i-1家店鋪不能洗劫,否則會觸發報警器,故此時f[i] = f[i-2] + w,w表示洗劫第i家店鋪可以獲得的現金。故狀態轉移方程為f[i] = max(f[i-1],f[i-2]+w),i >= 2。這裡的邊界狀態為f[0] = 0,f[1] = w1,因為只有一家商鋪時選擇洗劫必然是最優選擇。
#include #include using namespace std;
const int n = 100005;
int f[n];
int main()
printf("%d\n",f[n]);
}return 0;
}
方法二:狀態機
有限狀態機(finite-state machine)又稱有限狀態自動機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。在本題中,當我們從前往後遍歷到第i個商店時,用0表示不洗劫該商店,1表示洗劫該商店。
則當前狀態為洗劫了第i個商店時,狀態為1,下乙個商店只能不洗劫,即狀態1只能轉移到狀態0;當前狀態為0,即沒有洗劫第i個商店時,下乙個狀態可以不洗劫也可以洗劫,即狀態0既可以轉移到狀態0,也可以轉移到狀態1,本題的狀態機如上圖所示。
設f[i]0]表示在前i家店鋪中不洗劫第i家店鋪,f[i][1]表示洗劫第i家店鋪,狀態轉移方程為f[i][1] = f[i-1][0] + w,f[i][0] = max(f[i-1][0],f[i-1][1]),最後要求的最大現金等於max(f[n][0],f[n][1])。
#include #include using namespace std;
const int n = 100005;
int f[n][2];
int main()
printf("%d\n",max(f[n][0],f[n][1]));
}return 0;
}
由於第i個狀態只能由第i - 1個狀態轉移而來,所以可以不用陣列,只用兩個變數p,q表示0與1兩種狀態即可。
#include #include using namespace std;
int main()
printf("%d\n",max(p,q));
}return 0;
}
1049 大盜阿福
阿福是一名經驗豐富的大盜。趁著月黑風高,阿福打算今晚洗劫一條街上的店鋪。這條街上一共有 n 家店鋪,每家店中都有一些現金。阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街上的報警系統才會啟動,然後警察就會蜂擁而至。作為一向謹慎作案的大盜,阿福不願意冒著被警察追捕的風險行竊。他想知道,在不驚動...
23 大盜阿福
描述 阿福是一名經驗豐富的大盜。趁著月黑風高,阿福打算今晚洗劫一條街上的店鋪。這條街上一共有 n 家店鋪,每家店中都有一些現金。阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街上的報警系統才會啟動,然後警察就會蜂擁而至。作為一向謹慎作案的大盜,阿福不願意冒著被警察追捕的風險行竊。他想知道,在...
23 大盜阿福
阿福是一名經驗豐富的大盜。趁著月黑風高,阿福打算今晚洗劫一條街上的店鋪。這條街上一共有 n 家店鋪,每家店中都有一些現金。阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街上的報警系統才會啟動,然後警察就會蜂擁而至。作為一向謹慎作案的大盜,阿福不願意冒著被警察追捕的風險行竊。他想知道,在不驚動...