hdu 5330 Route Statistics(状压dp)
来源:互联网 发布:制作桌面的软件 编辑:程序博客网 时间:2024/06/05 16:11
题意:给出n个长度<=11的只含有012的串,定义2个串的距离为所有对应位相减的绝对值的和。求距离0到2×m-1的对数。
做法:挺难想的一个状压dp。只要把跟每个串的距离为x的有多少个算出来就可以求出最后的答案了。考虑一下子问题,我们只考虑与后几位的距离为x的有多少个,但是这样没法递推,因为前面的不知道,所以我们可以把前面的补全,故就有了dp[s1][s2][k]代表一些串的前缀就是s1,与s1+s2这个串的距离差为k的个数。我们可以发觉|s1|+|s2| = m,所以我们可以把前2维变成1维。
如果用刷表法就不用像题解填表法那样有9种情况了,只有3种情况,把第i位当作0,1,2即可。
假设第i位是1,转移就是
1.dp[s1-'1']['0'+s2][k+1] += dp[s1][s2][k].
2. dp[s1-'1']['1'+s2][k] += dp[s1][s2][k],
3. dp[s1-'1']['2'+s2][k+1] += dp[s1][s2][k].
真正写的过程中只要把第i位换成0,1,2就可以了。
初始值的设定是dp[s][空][0] = s这个串的个数。
AC代码:
#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdlib>#include<stack>#include<queue>#include<set>#include<map>#include<cmath>#include<ctime>#include<string.h>#include<string>#include<sstream>#include<bitset>using namespace std;#define ll __int64#define ull unsigned __int64#define eps 1e-8#define NMAX 1000000010#define MOD 1000000007#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define PI acos(-1)template<class T>inline void scan_d(T &ret){ char c; int flag = 0; ret=0; while(((c=getchar())<'0'||c>'9')&&c!='-'); if(c == '-') { flag = 1; c = getchar(); } while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); if(flag) ret = -ret;}const int maxn = 90000+10;int dp[2][200000][25];int cnt[200000];char s[20];int the[20],m;ll ans[30];int main(){#ifdef GLQ freopen("input.txt","r",stdin);// freopen("o1.txt","w",stdout);#endif the[0] = 1; for(int i = 1; i <= 11; i++) the[i] = the[i-1]*3; int _t; scanf("%d",&_t); while(_t--) { int n; scanf("%d%d",&n,&m); for(int i = 0; i < the[m]; i++) cnt[i] = 0; for(int i = 0; i < n; i++) { scanf("%s",s); int x = 0; for(int j = 0; j < m; j++) x = x*3+s[j]-'0'; cnt[x]++; } int f = 0; for(int i = 0; i < the[m]; i++) for(int j = 1; j <= 2*m; j++) dp[0][i][j] = 0; for(int i = 0; i < the[m]; i++) dp[0][i][0] = cnt[i]; for(int i = 0; i < m; i++) { for(int j = 0; j < the[m]; j++) for(int k = 0; k <= 2*m; k++) dp[f^1][j][k] = 0; for(int j = 0; j < the[m]; j++) for(int k = 0; k <= 2*m; k++) if(dp[f][j][k]) { int tmp = j/the[i]%3; for(int l = 0; l <= 2; l++) { int x = j-(tmp-l)*the[i]; dp[f^1][x][k+abs(l-tmp)] += dp[f][j][k]; } } f ^= 1; } memset(ans,0,sizeof(ans)); for(int i = 0; i < the[m]; i++) { if(!cnt[i]) continue; ans[0] += (ll)cnt[i]*(cnt[i]-1); for(int j = 1; j <= 2*m; j++) { ans[j] += (ll)cnt[i]*dp[f][i][j]; } } for(int i = 0; i <= 2*m; i++) printf("%I64d\n",ans[i]/2LL); } return 0;}
0 0
- hdu 5330 Route Statistics(状压dp)
- hdu 5330 Route Statistics 2015多校联合训练赛4 状态压缩
- HDU 4176 Class Statistics
- HDU 4240 Route Redundancy
- HDU 4240 Route Redundancy
- HDU 4628状压DP
- HDU 4539 状压DP
- HDU 1074 状压DP
- HDU 3182 状压DP
- hdu 4284(状压dp)
- hdu 2167(状压dp)
- hdu 4539(状压dp)
- hdu 4114(状压dp)
- HDU 4539 状压DP
- hdu 3001 状压DP
- HDU 4892 状压dp
- HDU 5045 DP+状压
- hdu-1074(状压dp)
- 日经春秋 20151008
- 点击回退键时出现连续返回的情况
- 代理反向传值
- C++中引用和指针的区别
- 深入浅出谈计算机语言的发展
- hdu 5330 Route Statistics(状压dp)
- flatmap详解
- C语言运算符
- list列表获取当前行数据【WeX5】
- UC应用中心数据 HTML5应用添加近亿次
- nyoj 苹果 289 (简单01背包)
- 写让别人能读懂的代码
- 1009. Product of Polynomials (25)
- NSString 对象的创建