Why so serious? --[NKU]schindlerlee

2010-02-07.sgu502状态压缩dp

2010-02-07.sgu502状态压缩dp <推荐题目>
sgu502:状态压缩dp
首先要知道这样一个事实
如果有5个数,要填充到如下x的位置上
*xx*x*x**x
那么只要这5个数产生的部分模的结果:
(x + x * 10^3 + x * 10^5 + x * 10^7 + x * 10^8) % 17
的结果相同,那么这5个数能产生这个相同结果的所有排列都是等价的。
这和使用状态压缩进行优化的哈密顿路径的搜索方法是一样的(想要详细的了解这个问题可以参考
MasterLuo的文章,我觉的写的很好, http://www.cppblog.com/EyeOfProvidence/archive/2010/01/10/105356.html
pku2288就是关于这个问题的一个应用)

如下的dfs中,
stat表示所有可用位的使用状态
mod表示前step个数产生的部分模。
step表示为第step个数。

对于刚才说的事实,如果前step个数填充的状态是相同的,那么所有模相等的状态就可以合并
也就是将前step个数的占用同样的step个位能产生的 P(step,step)个状态,减少到17个
 1 
 2 #define bin(x) (1 << (x))
 3 const int N = 20;
 4 char s[N];
 5 int num[N],len,out[N],ten[N],val[N];
 6 bool vis[bin(19)][19];
 7 
 8 bool dfs(int stat,int mod,int step)
 9 {
10   if (vis[stat][mod]) { return false; }
11   vis[stat][mod] = true;
12 
13   if (step == len) { return mod == 0; }
14   for (int i = 0;i < len; i++) {
15       if (stat & bin(i)) { continue; }
16       if (num[step] == 0 && i == len-1) { continue; } //第一位不能为0
17       out[i] = num[step];
18       if (dfs(stat | bin(i),(mod + num[step] * val[i])%17,step + 1)) {
19           return true;
20       }
21   }
22   return false;
23 }
24 //http://www.cppblog.com/schindlerlee
25 int main()
26 {
27   int i,j,k;
28   scanf("%s",s);
29   len = strlen(s);
30   val[0= 1;
31   for (i = 1;i < len;i++) { val[i] = (val[i-1* 10% 17; }
32   for (i = 0;i < len;i++) { num[i] = s[i] - '0'; }
33   if(dfs(0,0,0)) {
34       for (i = len - 1;i >= 0;i--) {
35           printf("%d",out[i]);
36       }
37       printf("\n");
38   }else {
39       printf("-1\n");
40   }
41 
42   return 0;
43 }



posted on 2010-02-07 00:48 schindlerlee 阅读(1020) 评论(0)  编辑 收藏 引用 所属分类: 解题报告


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理