zoukankan      html  css  js  c++  java
  • 2013多校第四场

    hdu 4632

    题意:给你一个长度为n的字符串,求包含几个回文序列?

    分析:dp[i][j]表示区间[l,r]内包含的回文序列的个数,

    dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1];  if (s[i] == s[j] ) dp[i][j] += dp[i+1][j-1]+1;

    也可以用别的递推方式,比如dp[i][j] = SUM(dp[k][j-1]+1)+1( s[k] == s[j] ,i<=k<j )

    可以递推求dp[i][j] = dp[i+1][j] + tmp ;这样时间还是O(n^2);

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<vector>
     7 #include<cstdlib>
     8 #include<set>
     9 using namespace std;
    10 const int N = 1000+10;
    11 const int Mod = 10007;
    12 int dp[N][N];
    13 char s[N];
    14 int n;
    15 int dfs(int l,int r){
    16     if (r<l) return 0;
    17     if (dp[l][r]) return dp[l][r];
    18     if (l == r) return dp[l][r] = 1;
    19     dp[l][r] = 0;
    20     dp[l][r] +=( dfs(l,r-1)+dfs(l+1,r) - dfs(l+1,r-1) );
    21     if (s[l] == s[r]) dp[l][r] += dfs(l+1,r-1)+1;
    22     return dp[l][r] %= Mod;
    23 }
    24 int main(){
    25     int T,cas = 0; scanf("%d",&T);
    26     while (T--){
    27         scanf("%s",s);
    28         memset(dp,0,sizeof(dp));
    29         n = strlen(s);
    30         dfs(0,n-1);
    31         printf("Case %d: %d
    ",++cas,dp[0][n-1]);
    32     }
    33     return 0;
    34 }
    View Code
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<iostream>
     5 #include<cmath>
     6 using namespace std;
     7 const int N = 1000+10;
     8 const int Mod = 10007;
     9 int dp[N][N];
    10 int n;
    11 char s[N];
    12 
    13 void solve(){
    14     for (int i = 0; i < n; i++){
    15         int tmp = 1;
    16         dp[i][i] = 1;
    17         for (int j = i-1; j >= 0; j--){
    18             if (s[j] == s[i]){
    19                 tmp = (tmp + dp[j+1][i-1]+1)%Mod;
    20             }
    21             dp[j][i] = (dp[j][i-1]+tmp) % Mod;
    22         }
    23     }
    24     printf("%d
    ",dp[0][n-1]);
    25 }
    26 int main(){
    27     int T,cas=0; scanf("%d",&T);
    28     while (T--){
    29         scanf("%s",s);
    30         n = strlen(s);
    31     
    32         printf("Case %d: ",++cas);    
    33         solve();
    34     }
    35     return 0;
    36 }
    View Code

     hdu 4638

    题意:给你一个序列1~n,询问[l,r]区间内有几段连续的值;

    分析:离线,按右端点排序,从左往由扫描,每次碰到新的数a,就看是否前面出现过他的朋友,如果出现一个a-1,那么前面包含a-1的段就不需要再被统计到了,所以把a-1的位置

    -1,如果询问的区间不包含a-1出现的位置,同理如果前面出现a+1;如果前面出现a-1,a+1,那么说明前面肯定至少有两段,分别包含a-1,a+1,现在出现a,把这两段合并,所以a-1位置-1,a+1,位置也-1,这样-1的个数就是不会被统计到的个数,r-l+1-(-1的个数)就是段数;

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<vector>
     7 #include<cstdlib>
     8 #define mk make_pair
     9 #define pbk push_back
    10 using namespace std;
    11 const int N = 100000+10;
    12 typedef pair<int,int > pii;
    13 int a[N],pos[N];
    14 int n,m;
    15 vector<pii> g[N];
    16 int ans[N];
    17 struct BIT{
    18     int c[N];
    19     int lowbit(int x){
    20         return x&(-x);
    21     }
    22     void init(){
    23         memset(c,0,sizeof(c));
    24     }
    25     void ins(int x,int v){
    26         for (int i = x; i < N; i += lowbit(i)){
    27             c[i] += v;
    28         }
    29     }
    30     int get(int x){
    31         int ret = 0;
    32         for (int i = x; i > 0; i -= lowbit(i)){
    33             ret += c[i];
    34         }
    35         return ret;
    36     }
    37 }H;
    38 void solve(){
    39     H.init();
    40     for (int i = 1; i <= n; i++ ){
    41         if (a[i] != 1 && pos[a[i]-1] < i){
    42             H.ins(pos[a[i]-1], -1);
    43         }
    44         if (pos[a[i]+1] < i && a[i] != n){
    45             H.ins(pos[a[i]+1], -1);
    46         }
    47         for (int j = 0; j < g[i].size(); j++){
    48             int u = g[i][j].first, id = g[i][j].second;
    49             ans[id] = (i - u + 1) + ( H.get(i) - H.get(u-1) );
    50         }
    51     }
    52     for (int i = 1; i <= m; i++){
    53         printf("%d
    ",ans[i]);
    54     }
    55 }
    56 void check(){
    57     for (int i = 1; i <= n; i++){
    58         cout<<a[i]<<" ";
    59     }cout<<endl;
    60     for (int i = 1; i <= n; i++)  cout<<pos[i]<<" "; cout<<endl;
    61 }
    62 int main(){
    63     int T; scanf("%d",&T);
    64     while (T--){
    65         scanf("%d%d",&n,&m);
    66         for (int i = 1; i <= n; i++){
    67              scanf("%d",a+i); pos[ a[i] ] = i;
    68         }
    69         //check();
    70         for (int i = 1; i <= m; i++) g[i].clear();
    71         for (int i = 1; i <= m; i++){
    72             int u,v; scanf("%d%d",&u,&v);
    73             g[v].pbk(mk(u,i));
    74         }
    75         solve();
    76         
    77     }
    78     return 0;
    79 }
    View Code

     hdu 4640

    题意:n个岛,m条路分别连接各岛且有一个花费,k个学妹在岛上求救,问3个人解救所有妹子的最小花费,限制,一个岛只能让一个人经过,(可以重复经过);

    分析:因为人是一样的,所以可以预处理出所有1个人能达到的所有状态,然后在递推出3个人能达到的最小花费;O(3^n*3),T = 150,比较糟糕..

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<vector>
     7 #include<cstdlib>
     8 #include<queue>
     9 #define mk make_pair
    10 #define pbk push_back
    11 using namespace std;
    12 typedef pair<int,int> paii;
    13 typedef long long LL;
    14 const int N = 17;
    15 int n,m;
    16 vector<paii> g[N];
    17 int tar;
    18 int dis[1<<N][N];
    19 int dp[3][1<<N];
    20 queue<paii> q;
    21 void init(){
    22     for (int i = 0; i < (1<<n); i++) for (int j = 0; j < n; j++) dis[i][j] = -1;
    23     while (!q.empty()) q.pop();
    24 
    25     dis[1][0] = 0;
    26     q.push(mk(0,1));
    27     while (!q.empty()){
    28         paii tp = q.front(); q.pop();
    29         int f1 = tp.first, f2 = tp.second;
    30         for (int i = 0; i < g[f1].size(); i++){
    31             int v = g[f1][i].first, s = g[f1][i].second;
    32             int c = f2|(1<<v);
    33             if (dis[c][v] == -1 || dis[c][v] > dis[f2][f1] + s){
    34                 dis[c][v] = dis[f2][f1] + s;
    35                 q.push(mk(v,c));
    36             }
    37         }    
    38     }
    39 }
    40 void Min(int &x,int y){
    41     if (y == -1) return;
    42     if (x == -1) x = y;
    43     else x = min(x,y);
    44 }
    45 void solve(){
    46     
    47     for (int j = 0; j < 3; j++) for (int i = 0; i < (1<<n); i++) dp[j][i] = -1;
    48     for (int i = 0; i < (1<<n); i++){
    49         for (int j = 0; j < n; j++){
    50             Min(dp[0][i], dis[i][j]); 
    51         }
    52     }
    53     for (int i = 0; i < (1<<n); i++){
    54         if (i&1)
    55         for (int j = i; j ; j = i&(j-1)){
    56             if (dp[0][j|1] != -1 && dp[0][(i^j)|1] != -1)
    57                 Min(dp[1][i],max(dp[0][j|1],dp[0][(i^j)|1]));
    58         }
    59     }
    60 
    61     int ans = -1;
    62     for (int i = 0; i < (1<<n); i++){
    63         if (i&1)
    64         for (int j = i; j ; j = i&(j-1)){
    65             if (dp[0][j|1] != -1 && dp[1][(i^j)|1] != -1){                
    66                 Min(dp[2][i],max(dp[0][j|1],dp[1][(i^j)|1]));
    67 
    68             }
    69             if ( (i&tar) == tar ){
    70                 Min(ans,dp[2][i]);
    71             }
    72         }
    73     }
    74 
    75     printf("%d
    ",ans);
    76 }
    77 int main(){
    78     int T, cas = 0; scanf("%d",&T);
    79     while (T--){
    80         printf("Case %d: ",++cas);
    81         scanf("%d%d",&n,&m);    
    82         for (int i = 0; i < n; i++) g[i].clear();
    83         for (int i = 0; i < m; i++){
    84             int u,v,s;
    85             scanf("%d%d%d",&u,&v,&s);
    86             g[u-1].pbk(mk(v-1,s));
    87             g[v-1].pbk(mk(u-1,s));
    88         }
    89         tar = 1;
    90         int k; scanf("%d",&k);
    91         for (int i = 0; i < k; i++){
    92             int t; scanf("%d",&t);
    93             tar |= 1<<(t-1);
    94         }
    95         init();
    96         solve();
    97     }
    98     return  0;
    99 }
    View Code

     hdu 4634

    题意:一个图,一个人,4种走法,会被强制转弯(但不算转弯次数),要拿到所有钥匙,问最少转弯次数;

    分析:基础BFS,细节比较多。

    trick: 判边界的时候错了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<vector>
      7 #include<cmath>
      8 #include<map>
      9 #include<queue>
     10 #define mk make_pair
     11 #define pbk push_back
     12 using namespace std;
     13 const int N = 200+10;
     14 char mz[N][N];
     15 int n,m;
     16 map<int,int> vis[N][N][4];
     17 inline void debug(char s){
     18     for (int i = 0; i < 4; i++) cout<<char(s);
     19     cout<<endl;
     20 }
     21 struct node{
     22     int x,y,c,d,key;
     23     node(){}
     24     node(int x,int y,int c,int d,int key):x(x),y(y),c(c),d(d),key(key){}
     25     bool operator < (const node &p)const{
     26         return c > p.c;
     27     }    
     28     void ot(){
     29         cout<<x<<" "<<y<<" "<<c<<" ++ "<<d<<" "<<key<<endl; 
     30     
     31     }
     32 };
     33 const int dx[4]={0,0,1,-1};
     34 const int dy[4]={1,-1,0,0};
     35 int sx,sy,ex,ey;
     36 
     37 int tar_key,cnt_key;
     38 priority_queue<node> q;
     39 int ti_clock;
     40 
     41 int IsInMz(int x,int y){
     42     if (x < 0 || x >= n  || y < 0 || y >= m) return 0;
     43     return 1;
     44 }
     45 void GO(int x,int y,int d,int &nx, int &ny, int &key){
     46     nx = x; ny = y;
     47     while (1){
     48         nx += dx[d];
     49         ny += dy[d];
     50         if (IsInMz(nx,ny) == 0) {
     51             return ;
     52         }
     53         if (mz[nx][ny] == '#') {
     54             nx -= dx[d];
     55             ny -= dy[d];
     56             return ;
     57         }
     58         if (mz[nx][ny] == 'L' || mz[nx][ny] == 'R' || mz[nx][ny] == 'U' || mz[nx][ny] == 'D') return ;    
     59         if (mz[nx][ny] == 'E'){
     60             if (key == tar_key) return ;    
     61         }
     62         if (mz[nx][ny] >= '0'  && mz[nx][ny] <= '9'){
     63             key |= 1<<(mz[nx][ny] - '0');
     64         } 
     65     }
     66 }
     67 int IDX(char s){
     68     if (s == 'L') return 1;
     69     if (s == 'R') return 0;
     70     if (s == 'U') return 3;
     71     if (s == 'D') return 2;
     72 }
     73 void solve(){
     74     while (!q.empty()) q.pop();    
     75     ti_clock++;    
     76     for (int  i = 0; i < 4; i++) {
     77         q.push(node(sx,sy,1,i,0));
     78         if (vis[sx][sy][i][0] != ti_clock) vis[sx][sy][i][0] = ti_clock;
     79     }
     80     int ans = -1;
     81     while (!q.empty()){
     82         node u = q.top(); q.pop();
     83         if (u.x == ex && u.y == ey  && u.key == tar_key){
     84             if (ans == -1 || ans > u.c){
     85                 ans = u.c;
     86             }
     87             continue;
     88         }
     89         int nx, ny, key = u.key;
     90         GO(u.x, u.y, u.d, nx, ny, key);
     91         if ( IsInMz(nx,ny) == 0) continue;
     92         if ( mz[nx][ny] == 'E') {
     93             if (key == tar_key){
     94                 if (vis[nx][ny][u.d][key] == ti_clock) continue;
     95                 vis[nx][ny][u.d][key] = ti_clock;
     96                 q.push(node(nx, ny ,u.c, u.d, key));
     97                 continue;
     98             }
     99         }
    100         
    101         if ( mz[nx][ny] == 'L' || mz[nx][ny] == 'R' || mz[nx][ny] == 'U' || mz[nx][ny] =='D'){
    102             int d = IDX(mz[nx][ny]);
    103             int c = u.c;
    104             if (vis[nx][ny][d][key] == ti_clock) continue;
    105             vis[nx][ny][d][key] = ti_clock;
    106             q.push(node(nx,ny,c,d,key));
    107             continue;
    108         }
    109         for (int i = 0; i < 4; i++){
    110             
    111             if (i != u.d){
    112                 if (vis[nx][ny][i][key] == ti_clock) continue;
    113                 vis[nx][ny][i][key] = ti_clock;
    114                 q.push(node(nx, ny, u.c+1, i, key));
    115             }
    116         }
    117     }
    118     printf("%d
    ",ans);    
    119 }
    120 int main(){
    121     ti_clock = 0; 
    122     while (~scanf("%d%d",&n,&m)){
    123         tar_key = 0; cnt_key = 0;
    124         for (int i = 0; i < n; i++){
    125             scanf("%s",mz[i]);
    126             for (int j = 0; j < m; j++){
    127                 if (mz[i][j] == 'S'){
    128                     sx = i; sy = j;
    129                 }
    130                 if (mz[i][j] == 'E'){
    131                     ex = i; ey = j;
    132                 }
    133                 if (mz[i][j] == 'K'){
    134                     tar_key |= 1<<cnt_key;
    135                     mz[i][j] = '0' + cnt_key;
    136                     cnt_key++;
    137                 }
    138             }
    139         }
    140         solve();
    141     }
    142     return 0;
    143 }
    View Code
  • 相关阅读:
    十七、mysql数据库备份
    消费端ACK和重回队列
    RabbitMQ TTL、死信队列
    消费端限流策略
    029异常处理
    028class_part2
    027class_part1
    026json和pickle,xml模块
    025__name__变量和目录结构规范
    024模块的概念
  • 原文地址:https://www.cnblogs.com/Rlemon/p/3232332.html
Copyright © 2011-2022 走看看