(intermediate) DFS的应用 UVA 12273 Palindromic DNA
来源:互联网 发布:json 判断key是否存在 编辑:程序博客网 时间:2024/04/28 20:20
A DNA sequence is composed of a series of four possible nucleobases, namely Adenine, Guanine, Thymine and Cytosine; we will refer to each of these bases by their initial. For our purposes, nucleobases have an associated cyclic ``order'':A is followed by G, which in turn is followed by T, which is followed byC, which is followed by A again. State-of-the-art research in genomics has revealed the startling fact that many diseases are caused by certain subsequences of bases not forming a palindromic sequence! Your mission as a leading researcher at ICPC laboratories is to take a DNA string S and a series of subsetsP1,..., Pt of indices to characters (nucleobases) inS, and transform S so that each of the restrictions of the resulting string toP1,..., Pt are palindromic. (The restriction ofS to a subset P = {i1,i2,..., ik} of indices, where 0i1 <i2 <...< ik < | S|, is the stringSi1Si2...Sik). It is possible to inspect any base ofS at will, but only three transformations can be applied to a base:
- Leave it unaltered.
- Increase it by 1 in the cyclic order of nucleobases (e.g. turnC into A).
- Decrease it by 1 (e.g. turn T into G).
By way of example, consider DNA sequence AGTAT. Number positions starting from0, and suppose we have the three subsets P1 = {1, 4}, P2 = {0, 1} andP3 = {0, 2, 4}. One solution is to increase the first character and decrease the last, yieldingS' = GGTAG. The restrictions of S' to P1, P2 and P3 areGG, GG and GTG, respectively; all of them are palindromic.
One case where no solution is possible is when the string is CATGC, and we require the subsequences determined by positions{0, 3} and {3, 4} be palindromic. Here, characters3, 0 and 4 would all need to become aT. But this entails modifying consecutive characters 3 and 4, which is not allowed.
Input
The first line of each test case has two integers N andT ( 1N10 000, 1T6 000), the sequence length and number of subsets to consider. The next line contains the DNA sequence of lengthN, all of whose characters are in ACGT. The subsets are described by the followingT lines. Each line starts by ``L:'', whereL (0LN) is the number of positions in the subset, and is followed by L distinct integers between 0 and N - 1 in increasing order. Subsets may overlap partially or totally.
A blank line separates different test cases. The input file is terminated by a line containing `0 0'.
Output
In a single line per test case, print `YES' if the task is solvable and `NO' otherwise.
Sample Input
5 3AGTAT2: 1 42: 0 13: 0 2 45 3CATGC0:2: 0 32: 3 40 0
Sample Output
YESNO
题意:给出一个DNA的序列,让后给出一些回文的集合,问你通过对DNA序列进行一定的改变,问能不能满足这些所有回文集合。当然改变时有要求的,相邻的两个不能同时改变,对于每一个字母,你可以+1、-1、+0,其中AGTC相当于对应是(0,1,2,3)
思路:首先根据回文的集合,我们能够得出这个DNA序列那些地方的字母应该是相等的,根据这个我们能把所有的字母分类,一种是不需要改变的,这些可以忽略,另外的就是按照那些必须要相同的分类。然后我们得到了图的点:这些不同的组。然后对于每一组有四种可能性,AGTC,那么分裂出四个点,分别代表选取的状态为AGTC,然后我们分别验证是否可以取,如果取了这个字母,把所有的相邻位置都看看是否会影响到别的组不能选什么字母,如果a组选了字母x,使得b组不能选字母y,那么我们就用一条有向边从a组字母x的顶点指向b组字母y的定点。这里面我们的有向边只取定点标号小的指向定点标号大的。因为我们后面dfs搜索的时候可以一组一组按顺序的搜索。不需要打乱顺序。其实我觉得我的办法可能还是有问题,我觉得会有数据使得我的代码超时的,但非常神奇的过了。。。。我说说我搜的办法是我们用一个vis数组表示这个顶点是否可取,如果是0,表示可以取,如果<0,表示不能取,那么再用一个sum数组表示每一组剩下的可取的状态,如果在搜索的过程中,发现后面有一个组的sum值已经为0了,那么就不必搜下去了,显然不会有解的。在搜的时候,如果我们为某一组选定了一个状态,就把这一组能指向 的组的vis减1,如果vis减为了-1,就把对应的sum也减一。直到每一组都分配了方案,就结束了。
代码:
#include<iostream>#include<algorithm>#include<cstdio>#include<string.h>#include<stack>#include<cstring>#include<vector>using namespace std;#define mp make_pairconst int maxn = 10000 + 5;vector<int> G[maxn*4];int sum[maxn];vector<int> block[maxn];int bkno[maxn];int bk_cnt;int S[maxn],P[maxn];char DNA[maxn];int n, m;void input(){scanf("%s", DNA);for (int i = 0; i < n; ++i){G[i].clear();if (DNA[i] == 'A') S[i] = 0;else if (DNA[i] == 'G') S[i] = 1;else if (DNA[i] == 'T') S[i] = 2;else if (DNA[i] == 'C') S[i] = 3;//printf("%d ", S[i]);}//cout << endl;for (int i = 0; i < m; ++i){int k; scanf("%d:", &k);for (int j = 0; j < k; ++j) scanf("%d", P + j);for (int j = 0; j < k / 2; ++j) {//printf("%d %d\n", P[j], P[k - 1 - j]);G[P[j]].push_back(P[k - 1 - j]);G[P[k - 1 - j]].push_back(P[j]);}}}int vis[maxn*4];void dfs(int x){if (vis[x]) return;vis[x] = 1;bkno[x] = bk_cnt;block[bk_cnt].push_back(x);for (int i = 0; i < G[x].size(); ++i){int y = G[x][i];dfs(y);}}void findblock(){memset(vis, 0, sizeof(vis));memset(bkno, -1, sizeof(bkno));bk_cnt = 0;for (int i = 0; i < n; ++i) if (!vis[i] && G[i].size()){block[bk_cnt].clear();dfs(i);sort(block[bk_cnt].begin(), block[bk_cnt].end());++bk_cnt;}}bool Ok(int s){int val = s % 4, bk = s / 4;//printf("%d %d\n", val,bk);stack<int> v;for (int i = 0; i < block[bk].size(); ++i){int x = block[bk][i];//printf("%d\n", x);if (S[x] != val && (S[x] + 1) % 4 != val && (S[x] + 3) % 4 != val) return false;if (S[x] == val) continue;int y = x + 1;//printf("%d %d\n", x, y);//printf("%d %d\n", bkno[x], bkno[y]);if (bkno[x] == bkno[y]){if (S[x] != val&&S[y] != val) return false;}else if (bkno[y] != -1 && bkno[y]>bkno[x]){for (int j = 0; j < 4; ++j) if (j != S[y]){v.push(bkno[y] * 4 + j);}}y = x - 1;if (y < 0 || bkno[x] >= bkno[y] || bkno[y]==-1) continue;for (int j = 0; j < 4; ++j) if (j != S[y]){v.push(bkno[y] * 4 + j);}}while (v.size()){G[s].push_back(v.top());v.pop();}return true;}bool dfs1(int x){if (x>=n) return true;for (int j = 0; j < 4; ++j) if (vis[x*4+j]>=0){bool flag = true;for (int k = 0; k < G[x * 4 + j].size(); ++k){int y = G[x * 4 + j][k];--vis[y];if (vis[y] == -1) --sum[y / 4];if (sum[y / 4] == 0) flag = false;}--vis[x*4+j];if (flag && dfs1(x + 1)) return true;++vis[x * 4 + j];for (int k = 0; k < G[x * 4 + j].size(); ++k){int y = G[x * 4 + j][k];++vis[y];if (vis[y] == 0) ++sum[y / 4];}}return false;}void solve(){memset(vis, -1, sizeof(vis));memset(sum, 0, sizeof(sum));//printf("%d\n", bk_cnt);for (int i = 0; i <= bk_cnt; ++i) sum[i] = 4;for (int i = 0; i < 4 * bk_cnt; ++i){G[i].clear();if (Ok(i)) vis[i] = 0;else sum[i / 4]--;}n = bk_cnt;//for (int i = 0; i < n; ++i)//{//printf("%d ", sum[i]);//}//cout << endl;if (dfs1(0)) printf("YES\n");else printf("NO\n");}int main(){while (scanf("%d%d", &n, &m) && n + m){input();findblock();solve();}}
- (intermediate) DFS的应用 UVA 12273 Palindromic DNA
- uva 12273 - Palindromic DNA(4SAT)
- (intermediate)DFS UVA 11604 General Sultan
- (intermediate) DFS (高精度+找环) UVA 1361 Cactus
- (intermediate) UVA 10358 Matrix
- (intermediate) UVA 1455 Kingdom
- (intermediate) UVA 1377 - Ruler
- (intermediate)DFS (边-双连通) UVA 10972 RevolC FaeLoN
- (intermediate)DFS (强连通+缩点+拓扑排序) UVA 11098 - Battle II
- (intermediate) 带下界的最小流 UVA 1440 - Inspection
- (intermediate) UVA 带下界的网络流 1369 - Travel
- uva 10765 dfs及其应用
- 动态规划intermediate:UVa 11456
- 动态规划intermediate:UVa 10239
- 动态规划intermediate:UVa 10604
- 基于Windows DNA的三层应用
- perl应用:DNA互补序列的获取
- UVa 10773 Back to Intermediate Math (数学&速度的分解&陷阱)
- ThreadLocal源码分析
- 电脑快捷键
- mtk android settings
- VS2008输入中文乱码
- DbDataAdapter 的Fill(DataTable dataTable) 和 Update(DataSet dataSet);方法的使用
- (intermediate) DFS的应用 UVA 12273 Palindromic DNA
- 数据库ORM框架GreenDao学习心得及使用总结
- js 动作与函数绑定
- Ural1574
- 694 - The Collatz Sequence
- Fragment+ActionBar实现标签页
- 互联网思维下的传统企业转型思考
- STL中map、set的数据结构及底层实现
- ubuntu 13.1 number lock open when startup