Best Sequence(poj 1699) 状压dp(TSP)

类似于前两天做的那个wordstack。状压的其实有时候爆搜+记忆化也差不多。

就是这个是要与之前的都重合,移位预处理要注意。

理解好第一个样例就行

/* ***********************************************
Author        :bingone
Created Time  :2014/12/9 22:48:56
File Name     :a.cpp
************************************************ */

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define  inf  0x3f3f3f3f
#define  maxn (10+10000)
using namespace std;
typedef long long ll;
int N,M,T;
char in[12][25];
int dp[1<<10][10];
int slen[10][10];
int len[10];
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
	scanf("%d",&T);
	while(T--){
		scanf("%d",&N);
		for(int i=0;i<N;i++)
			getchar(),scanf("%s",in[i]),len[i]=strlen(in[i]);
		memset(slen,0,sizeof(slen));
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				if(i==j) continue;
				int tmp;
				for(int k=0;k<len[i];k++){
					tmp=0;
					if(len[i]<len[j]){
                        for(int t=len[j]-1,p=len[i]-1-k;t>-1 && p>-1;t--,p--)
                            if(in[i][p]!=in[j][t])break;
                            else tmp++;
                        if(tmp==len[i]-k) slen[i][j]=max(tmp,slen[i][j]);
					}
					else{
                        for(int t=len[j]-1,p=len[j]-1-k;t>-1 && p>-1;t--,p--)
                            if(in[i][p]!=in[j][t])break;
                            else tmp++;
					if(tmp==len[j]-k) slen[i][j]=max(tmp,slen[i][j]);
					}
				}
			}
		}
		int rt=1<<N;
		memset(dp,0x3f,sizeof(dp));
		for(int i=0;i<N;i++) dp[1<<i][i]=len[i];
		for(int i=0;i<rt;i++){
			for(int j=0;j<N;j++){
				if( (i&(1<<j))==0 ) continue;
				if(dp[i][j]==inf) continue;
				for(int k=0;k<N;k++){
					if(i&(1<<k)) continue;
					dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+len[k]-slen[j][k]);
					//printf("%d\n",(i&(1<<k)));
						}
			}
		}int ans=inf;
		for(int i=0;i<N;i++) ans=min(ans,dp[(1<<N)-1][i]);
		printf("%d\n",ans);
		}
    return 0;
}
/*
3
2
ACCA
CC
5
TCGG
GCAG
CCGC
GATC
ATCG
3
TAC
ACT
TACTG

ans:6 11 7 特别注意第一个样例的意思
*/
时间: 2024-09-30 00:27:13

Best Sequence(poj 1699) 状压dp(TSP)的相关文章

POJ 1038 状压DP

一个公司生产一种2*3规模的芯片,但是原材料上面有一些地方是不能用来当作芯片材料的,给出原料大小,及上面不能做原料的点,问你怎么分解,可以使生成芯片最大化. 对M进行三进制状压 last数组存储第i-1行和i-2行状态,cur数组存储i行和i-1行状态 cur[k]=2; // 本行k位置和上行k位置都不可用 cur[k]=1; // 本行k位置可用,上行k位置不可用 cur[k]=0; // 本行和上行位置k均可用 必须用滚动数组,否则爆内存 #include "stdio.h" #

poj 1699 Best Sequence(AC自动机+状压DP)

题目链接:poj 1699 Best Sequence 题目大意:给定N个DNA序列,问说最少多长的字符串包含所有序列. 解题思路:AC自动机+状压DP,先对字符串构造AC自动机,然后在dp[s][i]表示匹配了s,移动到节点i时候的最短步数. #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <iostream> #include &

POJ 3254 (状压DP) Corn Fields

基础的状压DP,因为是将状态压缩到一个整数中,所以会涉及到很多比较巧妙的位运算. 我们可以先把输入中每行的01压缩成一个整数. 判断一个状态是否有相邻1: 如果 x & (x << 1) 非0,说明有相邻的两个1 判断一个状态能否放在该行: 如果 (a[i] & state) != state,说明是不能放置的.因为a[i]中存在某个0和对应state中的1,与运算之后改变了state的值 判断相邻两行的状态是否有同一列相邻的1: 如果(state & _state)不

POJ 3254 状压DP

题目大意: 一个农民有一片n行m列 的农场   n和m 范围[1,12]  对于每一块土地 ,1代表可以种地,0代表不能种. 因为农夫要种草喂牛,牛吃草不能挨着,所以农夫种菜的每一块都不能有公共边. 告诉你 n ,m 和那些地方能种菜哪些地方不能种菜,求农夫一共有多少种方案种菜 解法: 基本思想是状压 也就是用一个int 型的数代表一行的种菜策略,二进制的0代表该位不能种菜,1位代表能种菜,使用位运算使处理速度变快 对于单行行,最多有2^12 种情况,并且 2^12种情况里面还有很多不满足题意的

POJ 2411 状压DP经典

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 16771   Accepted: 9683 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

POJ 2686(状压DP

第一次做状压感觉那一长串for显示了这是个多么暴力的算法呢...1A了倒是挺顺的 #include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<utility> #include<vector> #include<cstring> #include<cmath> #define INF 0x3fffffff #d

poj 3311 状压DP

经典TSP变形 学到:1.floyd  O(n^3)处理随意两点的最短路 2.集合的位表示,我会在最后的总结出写出.注意写代码之前一定设计好位的状态.本题中,第0位到第n位分别代表第i个城市,1是已经走过,0没走过 那么DP方程  :dp[s][i]--当前在城市i.状态为s(s存储的是走过了那些城市) 3.最后要求形成回路,那么就是min(dp[1<<(n+1)-1][i],dp[0][i]) #include <cstdio> #include <cstring>

poj 3254 状压dp入门题

1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相邻,求有多少种放法. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #d

poj 2923 状压dp+01背包

好牛b的思路 题意:一系列物品,用二辆车运送,求运送完所需的最小次数,两辆车必须一起走 解法为状态压缩DP+背包,本题的解题思路是先枚举选择若干个时的状态,总状态量为1<<n,判断这些状态集合里的那些物品能否一次就运走,如果能运走,那就把这个状态看成一个物品.预处理完能从枚举中找到tot个物品,再用这tol个物品中没有交集(也就是两个状态不能同时含有一个物品)的物品进行01背包,每个物品的体积是state[i],价值是1,求包含n个物品的最少价值也就是dp[(1<<n)-1](dp