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 }
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 }
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 }
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 }
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 }