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

 

posted @ 2013-08-02 12:50  Rabbit_hair  阅读(313)  评论(0编辑  收藏  举报