原题链接:Problem - 1418C - Codeforces
题目大意: 有一个序列n个数,非0即1,有两个人,一个是你的朋友,一个是你。从左到右,从你的朋友先开始,每个人一次必须选一个或两个数。ta选完你选然后又是ta选...问你朋友最后得到数的最小值。
1.其实就是让你的朋友尽量得到更少的1,得到更多的0;
2.用0表示你朋友,1表示你自己。状态转移:用dp[i][0]表示打的第i个怪,且是你朋友打完的。dp[i][1]表示打的第i个怪,且是你打完的。
2.状态转移方程:
//如果朋友拿这个数,就取a[i - 1]是我最后拿的加上a[i]和a[i - 2]是我最后拿的加上..
dp[i][0] = min(dp[i - 1][1] + a[i], dp[i - 2][1] + a[i - 1] + a[i]); //朋友取的第一个数两个数中的第二个数
dp[i][1] = min(dp[i - 1][0], dp[i - 2][0]);
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ios ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for (int i = n; i >= (1); --i)
typedef long long ll;
#define sqar(x) ((x)*(x))const int N = 2e5 + 10;
int dp[N][2]; //第i关的时候分别是朋友取a[i]这个值还是我取这个值时朋友的最小值 0:朋友 1 :我
int a[N];int main(){int n,t;cin >> t;while(t--){cin >> n;rep(i, n) cin >> a[i];dp[1][0] = a[1]; dp[1][1] = INF; //初始化dp[2][0] = a[1] + a[2]; dp[2][1] = a[1]; //dp[i][0]、dp[i][1]都是朋友的最小值,所以dp[2][1]是a[1]而不是a[2] for(int i =3; i <= n; i++){dp[i][0] = min(dp[i - 1][1] + a[i], dp[i - 2][1] + a[i - 1] + a[i]); //上一次我选了一个还是两个dp[i][1] = min(dp[i - 1][0], dp[i - 2][0]);}cout << min(dp[n][0], dp[n][1]) << endl;}return 0;
}