LightOJ 1422 Halloween Costumes (区间dp)

题意和思路转自https://blog.csdn.net/yyyy_h/article/details/50557550

题意:

告诉有n场晚会中需要穿的衣服,衣服是可以套在其他衣服外面的,也就是说如果顺序为 1 2 1,那么可以将2套在1外面,第三场晚会需要穿1的时候把2脱掉即可,这样就只需要穿两次衣服。

题目是再告诉了顺序之后需要求出在某种序列下最少需要穿多少次衣服。


样例 1 2 1 2: ①穿1   ②穿2  ③脱2  ④穿2      或者     ①穿1   ②脱1穿2  ③穿1  ④脱1    均输出  3


思路:

感觉思路比较巧妙,首先我们使用dp[a][b]来表示区间 a~b 的答案,那么对于第 i 件衣服,我们有


①:如果在之后的区间内都不再重复利用这件衣服,那么明显  dp[i][j] = dp[i+1][j] + 1;


②:如果在之后的区间 i+1 ~ j 中存在一件衣服 k 是跟 i 一样的,那么我们便可以考虑是不是可以将i那件衣服在k这个地方重复利用,

那么转移方程为  dp[i][j] = min(dp[i][j] , dp[i][k-1]+dp[k+1][j]);

或者认为k那件衣服是来自于i 转移方程为    dp[i][j] = min(dp[i][j] , dp[i+1][k-1]+dp[k][j]); //这个转移方程和上一个同意,可以任选一个。


#include <bits/stdc++.h>

using namespace std;
#define pb push_back
#define pii pair<int, int>
#define mk make_pair
#define fi first
#define se second
#define ALL(A) A.begin(), A.end()
#define sc(x) scanf("%d", &x)
#define pr(x) printf(#x":%d\n", x)
#define fastio ios::sync_with_stdio(0), cin.tie(0)
#define frein freopen("in.txt", "r", stdin)
#define freout freopen("out.txt", "w", stdout)
#define freout1 freopen("out1.txt", "w", stdout)
#define debug cout<<"???"<<endl
#define mid ((l+r)>>1)
#define lson ((rt)<<1|1)
#define rson (((rt)<<1)+2)
#define ABS(x) ((x)<0?(-(x)):(x))
//#define br puts("")
#define sqr(x) ((x)*(x))
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int INF = 0x3f3f3f3f;
//const ll mod = 1e9+7;
//const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b){if(!b)return a;return gcd(b,a%b);}

const int maxn = 105;

int dp[maxn][maxn], n, a[maxn];

void MIN(int& a, int b){
    a = (a<b)?a:b;
}

int solve(){
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i < n; i++) dp[i][i] = 1;
    for(int len = 2; len <= n; len++){
        for(int l = 0, r = len-1; r < n; l++, r++){
            dp[l][r] = dp[l][r-1]+1;
            for(int j = l; j < r; j++){
                if(a[j] != a[r]) continue;
                MIN(dp[l][r], dp[l][j]+dp[j+1][r-1]);
            }
        }
    }
    return dp[0][n-1];
}

int main(){
    int T; sc(T);
    for(int kase = 1; kase <= T; kase++){
        sc(n);
        for(int i = 0; i < n; i++) sc(a[i]);
        printf("Case %d: %d\n", kase, solve());
    }
    return 0;
}

阅读更多
个人分类: DP
相关热词: lightoj
上一篇2015-2016 Petrozavodsk Winter Training Camp, Makoto rng_58 Soejima Сontest 4
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭