Pieces(hdu4628,状态压缩的动态规划)

来源:互联网 发布:龙城飞将 知乎 编辑:程序博客网 时间:2024/06/07 06:05

http://acm.hdu.edu.cn/showproblem.php?pid=4628

Pieces

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 536    Accepted Submission(s): 317

Problem Description

You heart broke into pieces.My string broke into pieces.But you will recover one day,and my string will never go back.

Given a string s.We can erase a subsequence of it if this subsequence is palindrome in one step. We should take as few steps as possible to erase the whole sequence.How many steps do we need?

For example, we can erase abcba from axbyczbea and get xyze in one step.

Input

The first line contains integer T,denote the number of the test cases. Then T lines follows,each line contains the string s (1<= length of s <= 16).

T<=10.

Output

For each test cases,print the answer in a line.

Sample Input

2

aa

abb

Sample Output

1

2

Source

2013 Multi-University Training Contest 3

Recommend

zhuyuanchen520

解析:

题意:给出一个字符串,要求最少需要多少步可以将其删完。其中回文序列可以一次性删掉

思路:

状态压缩的动态规划:

由于数据比较小,所以可以暴力枚举每一种状态然后判断其合法性。

最后用状态转移方程解决即可

562MS 1196K 862 B G++

dp[i]=min(dp[i],dp[i-j]+1);表示i状态下的最小步数,ji的合法子集;

步骤:

1,枚举每一种状态并记录其合法性

2.在状态转移方程中更新值

仿标称写的

*/

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;const int maxn=1<<16+1;int inf=10000000;char ch[maxn];int dp[maxn],can[maxn];int min(int a,int b){return a<b? a:b;}void work(){   int i,j,ok,n,k;     int s,t;scanf("%s",ch);n=strlen(ch);for(i=0;i<(1<<n);i++)//枚举每一种状态并且记录其合法性{  char temp[maxn];    k=0;for(j=0;j<n;j++)//举出在i状态下的情形if(i>>j&1)temp[k++]=ch[j];ok=1;for(s=0,t=k-1;t>s;t--,s++)//判断该状态是否合法,即是否是回文字{if(temp[s]!=temp[t])   {   ok=0;   break;   }}can[i]=ok;}dp[0]=0;for(i=1;i<(1<<n);i++){  dp[i]=inf;for(j=i;j>0;(--j)&=i)//枚举j状态下的子集{if(can[j])//如果该子集合法则列入方程计算{dp[i]=min(dp[i],dp[i-j]+1);}}}printf("%d\n",dp[(1<<n)-1]);}int main(){int T;scanf("%d",&T);while(T--){  memset(dp,0,sizeof(dp));work();}return 0;}/*1187MS66084K1347 BG++*/#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <cstring>#include <vector>#include <cassert>using namespace std;typedef long long int64;const int MAX_N = 16, INF = ~0U >> 2;int n;int dp[1 << MAX_N][MAX_N][MAX_N]; //rest,i,jchar s[MAX_N + 1];void work() {scanf("%s", s);n = strlen(s);for (int i = 0; i < n; ++i) {for (int j = i; j < n; ++j) {dp[0][i][j] = 0;//初始化为0}}for (int rest = 1; rest < (1 << n); ++rest) {for (int i = n - 1; i >= 0; --i) {for (int j = i; j < n; ++j) {//rest,i,jint&ret = dp[rest][i][j] = INF;//rest表示i与j之间的状态if (i < j)ret = min(dp[rest][i + 1][j], dp[rest][i][j - 1]);if (s[i] == s[j] && (rest >> i & 1) && (rest >> j & 1)) {//当第i个字符状态和第j的字符状态1int nrest = rest & (~(1 << i)) & (~(1 << j));//将i和j位置0if (nrest == 0)//若此时状态为全0,即此状态将字符串都删除了ret = min(ret, dp[nrest][i][j] + 1);elseret = min(ret, dp[nrest][i][j]);}}}for (int i = n - 1; i >= 0; --i) {for (int j = i; j < n; ++j) {dp[rest][i][j] = min(dp[rest][i][j], dp[rest][0][n - 1] + 1);}}}cout << dp[(1 << n) - 1][0][n - 1] << endl;}int main() {int T;cin >> T;while (T--) {work();}}


原创粉丝点击