zoukankan      html  css  js  c++  java
  • hdoj 4272 LianLianKan 数据太水

    点击打开链接

    题意:

    给出一个序列,其中距离不超过6的两个相同的数字可以消除掉(从上往下消,输入是从底向上的),问能不能全部消除。


    思路:

    状压dp http://www.cnblogs.com/swm8023/archive/2012/09/10/2679455.html

    因为最坏情况下,它后面的四个数字能被它前面的四个数字消掉,这样它就能和原来是它后面的第9个元素相消了,最多10个状态


    状态转移:

    如果st的第1说明这一位位为0,已经被消掉,d[i][st]=dp(i+1,next(st))。

    如果第1为为1,向后连续找至多五个为1的位,比较是否和第一位数字相同,如果相同,就将st的这两位置为0,然后

    d[i][st]=d(i+1,next(newst)),newst=st&~1&~(1<<k),其中x[k]==x[i]。

    next(st)这个函数是求将st传递到下一个位置时的状态,如果(n-(p+1) > 9) st=1<<9|st>>1,否则st=st>>1,因为只有当后面数字多于10个时,才会有新的数字加入到状态中。

    代码一:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define mem(a) memset(a,0,sizeof(a))
     5 #define mp(x,y) make_pair(x,y)
     6 const int INF = 0x3f3f3f3f;
     7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     8 inline ll read(){
     9     ll x=0,f=1;char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 //////////////////////////////////////////////////////////////////////////
    15 const int maxn = 1e3+10;
    16 
    17 int n;
    18 ll a[maxn];
    19 int dp[maxn][1<<10],full;
    20 
    21 int nx(int p,int st){
    22     if(n-(p+1) > 9) return (1<<9) | (st>>1);
    23     else return st>>1;
    24 }
    25 
    26 int dfs(int p,int st){
    27     if(p == n) return st==0;
    28     if(dp[p][st] != -1) return dp[p][st];
    29     dp[p][st] = 0; // 二维 表示在p这个位置[保证可以记忆化,不被覆盖] 从p开始的10个数字的状态为st时是否可消
    30 
    31     if((st&1) == 0) dp[p][st] = dfs(p+1,nx(p,st));
    32     else{
    33         int cnt = 0;
    34         for(int i=1; i<10; i++){
    35             if((1<<i & st) == (1<<i)){
    36              // if (1<<i&st){
    37                  // cout << "aa " << i << " " << st << " " << (1<<i&st) << endl;
    38                 cnt++;
    39                 if(cnt > 5) break;
    40                 if(a[p] == a[p+i]){
    41                     int newst = st & ~(1<<i) & ~1;
    42                     if(dfs(p+1,nx(p,newst))){
    43                         dp[p][st] = 1;
    44                         break;
    45                     }
    46                 }
    47             }
    48         }
    49     }
    50     return dp[p][st];
    51 }
    52 
    53 int main(){    
    54     while(scanf("%d",&n) != EOF){
    55         memset(dp,-1,sizeof(dp));
    56         for(int i=1; i<=n; i++)
    57             a[n-i] = read();
    58         full = (1<<min(n,10)) - 1;
    59 
    60         cout << dfs(0,full) << endl;        
    61     }
    62 
    63     return 0;
    64 }

    代码二: 直接dfs模拟

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define mem(a) memset(a,0,sizeof(a))
     5 #define mp(x,y) make_pair(x,y)
     6 const int INF = 0x3f3f3f3f;
     7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     8 inline ll read(){
     9     ll x=0,f=1;char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 //////////////////////////////////////////////////////////////////////////
    15 const int maxn = 1e3+10;
    16 map<int,int> mp;
    17 map<int,int>::iterator it;
    18 int a[maxn],used[maxn];
    19 
    20 int dfs(int n){
    21     while(n>0 && used[n]) n--;
    22     if(n==0) return 1;
    23     if(n==1) return 0;
    24     int i = 0;    
    25     int j = n-1;
    26     while(i<=5){
    27         if(j<=0) return 0;
    28         if(used[j]) {
    29             j--;
    30             continue;
    31         }
    32         if(a[n] == a[j]){
    33             used[j] = 1;
    34             if(dfs(n-1)) return 1;
    35             used[j] = 0;
    36         }
    37         i++;
    38         j--;
    39     }
    40     return 0;
    41 }
    42 
    43 int main(){
    44     int n;
    45     while(scanf("%d",&n)!=EOF){
    46         mp.clear();
    47         mem(used);
    48         for(int i=1; i<=n; i++){
    49             a[i] = read();
    50             mp[a[i]]++;
    51         }
    52 
    53         int flag = 1;
    54         for(it=mp.begin(); it!=mp.end(); it++){
    55             if(it->second % 2){
    56                 flag = 0;
    57                 break;
    58             }
    59         }
    60         if(!flag){
    61             cout << 0 << endl;
    62             continue;
    63         }
    64         // cout << 1 << endl;
    65         cout << dfs(n) << endl;
    66     }
    67 
    68 
    69     return 0;
    70 }
  • 相关阅读:
    在IDEA中使用maven
    使用IDEA创建JavaWeb项目 部署本地tomcat并运行
    Java
    c++
    Vue学习
    svn 小程序地址
    SVN 上传代码
    eclipse插件 --js
    https抓包
    eclipse 断点位置发生莫名其妙的位移
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827697.html
Copyright © 2011-2022 走看看