Ural 1519. Formula 1 优美的插头DP

 
分类: ACM_Ural ACM_插头DP   333人阅读  评论(0)  收藏  举报

今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的,由于要考虑好多东西,而且昨晚2点睡的有点困,最后终于磨蹭出来了,第一次的代码搓没关系,自己写的才重要。然后果然不出我所料,调试到了晚上才A了(一个郁闷的错误)。。。A的感觉真的是爽呀,虽然搞了差不多一天。当然自己写了自己想的代码后也要把代码优化,不然队友看不懂自己代码就囧了。。。


插头DP,建议大家想学的好好看看陈丹琦的国家集训队论文,这是个优美的DP。

http://www.docin.com/p-46797997.html


[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3.   
  4. #define LL __int64  
  5.   
  6. const int mod = 10007;  
  7.   
  8. //   哈希表  
  9. struct HASH{  
  10.     int head[mod+10], E, next[80000];  
  11.     LL val[80000], cnt[80000];  
  12.   
  13.     void init() {  
  14.         memset(head, -1, sizeof(head));  
  15.         E = 0;  
  16.     }  
  17.   
  18.     int findhash(LL x) {  
  19.         return (x%mod + mod)%mod;  
  20.     }  
  21.   
  22.     void add(LL x, LL sum) {  
  23.         int u = findhash(x);  
  24.         for(int i = head[u];i != -1;i = next[i]) if(val[i] == x) {  
  25.             cnt[i] += sum;  
  26.             return ;  
  27.         }  
  28.         val[E] = x;  
  29.         cnt[E] = sum;  
  30.         next[E] = head[u];  
  31.         head[u] = E++;  
  32.     }  
  33.   
  34. }biao1, biao2;  
  35.   
  36. int c[22], n, m, d[22];  
  37. //  编码  
  38. void get(LL x) {  
  39.     for(int i = m+1;i >= 1; i--) {  
  40.         c[i] = x&7;  
  41.         x /= 8;  
  42.     }  
  43. }  
  44. //  解码  
  45. LL getval() {  
  46.     LL ret = 0;  
  47.     for(int i = 1;i <= m+1; i++) {  
  48.         ret |= d[i];  
  49.         ret *= 8;  
  50.     }  
  51.     ret /= 8;  
  52.     return ret ;  
  53. }  
  54. //   转化成最小表示法  
  55. void change() {  
  56.     int vis[22];  
  57.     memset(vis, 0, sizeof(vis));  
  58.     int num = 1;  
  59.     for(int i = 1;i <= m+1;i ++) {  
  60.         if(!d[i])   continue;  
  61.         if(!vis[d[i]]) {  
  62.             vis[d[i]] = num;  
  63.             d[i] = num++;  
  64.         }  
  65.         else {  
  66.             d[i] = vis[d[i]];  
  67.         }  
  68.     }  
  69. }  
  70.   
  71. void fuzhi() {  
  72.     for(int i = 1;i <= m+1;i ++)    d[i] = c[i];  
  73. }  
  74.   
  75. char s[22][22];  
  76.   
  77. int main() {  
  78.     int i, j, k, l;  
  79.     while(scanf("%d%d", &n, &m) != -1) {  
  80.         for(i = 1;i <= n; i++)  
  81.             scanf("%s", s[i]+1);  
  82.         int tot = 0;  
  83.         for(i = 1;i <= n; i++)  
  84.             for(j = 1;j <= m; j++)  
  85.             if(s[i][j] == '.')  tot++;  
  86.         if(tot%2==1 || tot < 4) {  
  87.             puts("0");  
  88.             continue;  
  89.         }  
  90.         int tox  = -1, toy = -1;  
  91.         for(i = 1;i <= n; i++)  
  92.         for(j = 1;j <= m; j++) if(s[i][j] == '.') {  
  93.             tox = i;  
  94.             toy = j;  
  95.         }  
  96.         biao1.init();  
  97.         biao1.add(0, 1);  
  98.         LL ans = 0;  
  99.         for(i = 1;i <= n; i++){  
  100.             for(j = 0;j <= m; j++){  
  101.                 biao2.init();  
  102.                 for(l = 0;l < biao1.E; l++)  {  
  103.                     get(biao1.val[l]);  
  104.                     if(j == m) {  
  105.                         for(int ii = 2;ii <= m+1; ii++) d[ii] = c[ii-1];  
  106.                         d[1] = 0;  
  107.                         change();  
  108.                         LL now = getval();  
  109.                         biao2.add(now, biao1.cnt[l]);  
  110.                         continue;  
  111.                     }  
  112.                     if(c[j+1] && !c[j+2]) {  //  有左插头无上插头  
  113.                         if(s[i][j+1] != '.')  continue;  
  114.                         if(j+2 <= m) {  
  115.                             fuzhi();  
  116.                             d[j+1] = 0;d[j+2] = c[j+1];  
  117.                             change();  
  118.                             LL now = getval();  
  119.                             biao2.add(now, biao1.cnt[l]);  
  120.                         }  
  121.                         if(i < n) {  
  122.                             fuzhi();  
  123.                             change();  
  124.                             LL now = getval();  
  125.                             biao2.add(now, biao1.cnt[l]);  
  126.                         }  
  127.                     }  
  128.                     else if(!c[j+1] && c[j+2]) {  //  有上插头无左插头  
  129.                         if(s[i][j+1] != '.')  continue;  
  130.                         if(i < n) {  
  131.                             fuzhi();  
  132.                             d[j+1] = c[j+2]; d[j+2] = 0;  
  133.                             change();  
  134.                             LL now = getval();  
  135.                             biao2.add(now, biao1.cnt[l]);  
  136.                         }  
  137.                         if(j+2 <= m) {  
  138.                             fuzhi();  
  139.                             change();  
  140.                             LL now = getval();  
  141.                             biao2.add(now, biao1.cnt[l]);  
  142.                         }  
  143.                     }  
  144.                     else if(!c[j+1] && !c[j+2]) { //   左和上都无插头  
  145.                         if(s[i][j+1] != '.') {  
  146.                             fuzhi();  
  147.                             change();  
  148.                             LL now = getval();  
  149.                             biao2.add(now, biao1.cnt[l]);  
  150.                             continue;  
  151.                         }  
  152.                         if(j+2 <= m && i < n) {  
  153.                             fuzhi();  
  154.                             d[j+1] = d[j+2] = 13;  
  155.                             change();  
  156.                             LL now = getval();  
  157.                             biao2.add(now, biao1.cnt[l]);  
  158.                         }  
  159.                     }  
  160.                     else { //  左和上都有插头 ,  要判断左和上插头是否连通  
  161.                         if(c[j+2] == c[j+1]) {  
  162.                             int tot = 0;  
  163.                             for(int ii = 1;ii <= m+1; ii++) if(c[ii])  
  164.                                 tot++;  
  165.                             if(tot == 2 && i == tox && j+1 == toy) ans += biao1.cnt[l];  
  166.                         }  
  167.                         else {  
  168.                             if(s[i][j+1] != '.')    continue;  
  169.                             fuzhi();  
  170.                             for(int ii = 1;ii <= m+1; ii++) if(ii != j+1 && ii != j+2 && d[ii] == d[j+1]) {  
  171.                                 d[ii] = d[j+2];  
  172.                                 break;  
  173.                             }  
  174.                             d[j+1] = d[j+2] = 0;  
  175.                             change();  
  176.                             LL now = getval();  
  177.                             biao2.add(now, biao1.cnt[l]);  
  178.                         }  
  179.                     }  
  180.                 }  
  181.                 biao1 = biao2;  
  182.             }  
  183.         }  
  184.         printf("%I64d\n", ans);  
  185.     }  
  186.     return 0;  
  187. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值