递推DP URAL 1167 Bicolored Horses
题意:k个马棚,n条马,黑马1, 白马0,每个马棚unhappy指数:黑马数*白马数,问最小的unhappy值是多少
分析:dp[i][j] 表示第i个马棚放j只马的最小unhappy值,状态转移方程:dp[i][j] = min (dp[i][j], dp[i-1][k-1] + cur * (j - k + 1 - cur)); 表示k到j匹马放在第i个马棚的最小unhappy值,dp[0][0] = 0。由于黑马数是1的和,前缀sum[i]表示前i匹马黑马的个数,白马就是总个数-黑马数。
收获:简单递推DP
代码:
/************************************************ * Author :Running_Time * Created Time :2015-9-1 12:03:47 * File Name :URAL_1167.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 5e2 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int dp[N][N], sum[N], a[N]; int main(void) { int n, m; while (scanf ("%d%d", &n, &m) == 2) { memset (sum, 0, sizeof sum); for (int i=1; i<=n; ++i) scanf ("%d", &a[i]), sum[i] = sum[i-1] + a[i]; memset (dp, INF, sizeof (dp)); dp[0][0] = 0; for (int i=1; i<=m; ++i) { for (int j=1; j<=n; ++j) { for (int k=1; k<=j; ++k) { int cur = sum[j] - sum[k-1]; dp[i][j] = min (dp[i][j], dp[i-1][k-1] + cur * (j - k + 1 - cur)); } } } printf ("%d\n", dp[m][n]); } return 0; }
编译人生,运行世界!