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\n",++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\n",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\n",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\n",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\n",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

 

你可能感兴趣的:(2013多校第四场)