sizeoftank


  • 首页

  • 分类

  • 归档

HDU 1080 Human Gene Functions

发表于 2011-09-15 | 分类于 文章归档 | 阅读次数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1080

LCS的变种:
状态转移:dp[i][j] = MAX(dp[i-1][j-1]+cost[a[i]][b[j]],dp[i-1][j]+cost[a[i]][SPACE],dp[i][j-1]+cost[SPACE][b[j]])

先将A-C-G-T各个匹配的代价打个表,DP时注意状态的初始化!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 101
#define inf 0x0fffffff
int cost[5][5] = { {5,-1,-2,-1,-3},{-1,5,-3,-2,-4},{-2,-3,5,-2,-2},{-1,-2,-2,5,-1},{-3,-4,-2,-1,-inf}};
int dp[MAXN][MAXN];
enum GENE{GENEA,GENEC,GENEG,GENET,SPACE};
int MAX(int x,int y)
{
return x>y?x:y;
}
int Convert(char x)
{
switch(x)
{
case 'A':return GENEA;break;
case 'C':return GENEC;break;
case 'G':return GENEG;break;
case 'T':return GENET;break;
}
}
int DymanicSolve(int *a,int *b,int alen,int blen)
{
int i,j,k;
dp[0][0] = 0;
for (i = 1; i <= alen; i++)
dp[i][0] = dp[i-1][0]+cost[a[i]][SPACE];
for (j = 1; j <= blen; j++)
dp[0][j] = dp[0][j-1]+cost[SPACE][b[j]];
for (i = 1; i <= alen; i++)
for (j = 1; j <= blen; j++)
dp[i][j] = MAX(dp[i-1][j-1]+cost[a[i]][b[j]],MAX(dp[i-1][j]+cost[SPACE][a[i]],dp[i][j-1]+cb[j]][SPACE]));
return dp[alen][blen];
}
int main()
{
freopen("Sample Input.txt","r",stdin);
int SeqA[MAXN],Alen;
int SeqB[MAXN],Blen;
int T,i,j;
char c;
scanf("%d",&T);
while (T--)
{
scanf("%d",&Alen);
getchar();
for (i = 1; i <= Alen; i++)
{
c = getchar();
SeqA[i] = Convert(c);
}
getchar();
scanf("%d",&Blen);
getchar();
for (i = 1; i <= Blen; i++)
{
c = getchar();
SeqB[i] = Convert(c);
}
getchar();
printf("%d\n",DymanicSolve(SeqA,SeqB,Alen,Blen));
}
getch();
return 0;
}

HDU 1561 THE MORE,THE BETTER

发表于 2011-09-15 | 分类于 文章归档 | 阅读次数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561

这道题意思是给你一棵树,必须先攻下父母节点后才能攻下其孩子节点。

以0为树根,然后对树种的节点做背包~

看了别人的报告后敲的代码,第一个树形DP的练习~囧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 222
int M,N;
int Tree[MAXN][MAXN];
int count[MAXN];
int visit[MAXN];
int value[MAXN];
int dp[MAXN][MAXN];
enum boolean {FALSE,TRUE};
int MIN(int x,int y) { return x>y?x:y;}
int MAX(int x,int y) { return x<y?x:y;}
int DFS(int p)
{
int i,j,k,r;
visit[p] = TRUE;
for (i = 0; i <= count[p]; i++)
{
r = Tree[p][i];
if (visit[r]==FALSE)
DFS(r);
for (j = M; j>= 2; j--)
{
for (k = 1; k < j; k++)
{
if (dp[r][k]!=-1 && dp[p][j-k]!=-1)
dp[p][j] = MAX(dp[p][j],dp[p][j-k]+dp[r][k]);
}
}
return TRUE;
}
int main()
{
freopen("Sample Input.txt","r",stdin);
int i,p,j;
while (scanf("%d%d",&M,&N),M||N)
{
memset(count,-1,sizeof(count));
for (i = 1; i <= N; i++)
{
scanf("%d%d",&p,&value[i]);
Tree[p][++count[p]] = i;
dp[i][1] = value[i];
}
dp[0][1] = 0;
for (i = 0; i <= N; i++)
{
dp[i][0] = 0;
for (j = 2; j <= M; j++)
dp[i][j] = -1;
visit[i] = FALSE;
}
M++;
DFS(0);
printf("%d\n",dp[0][M]);
}
getch();
return 0;
}

HDU 3836 Equivalent Sets

发表于 2011-09-15 | 分类于 文章归档 | 阅读次数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3836

求至少需要添加多少条边,才能使这个图变成强连通图。

求强连通分支的算法:

STEP1:先DFS遍历图,记录DFS完成时间f[n]
STEP2:选择f[n]最大的(就是f[n]降序)再DFS反向图GT,得到各个强连通分量。

求出强分量后缩点处理得到分支图,对分支图的每个强连通分量统计出度和入度。只要在第二次DFS的过程中判断有没有访问其他已经找出的强连通分量(这边的证明过程在算法导论上P339有很详细的证明)。所以要把剩下的(还不能强连通的)几个强连通分量添加边形成整个强连通图,需要的边数就是:统计 入度=0 的顶点数 和 出度=0 的顶点数,选择两者中较大的一个,才能确保一个强连通图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 31000
#define MAX(a,b) (a)>(b)?(a):(b)
typedef struct EDGE
{
int adjvex;
struct EDGE *Next;
}EDGE;
typedef struct
{
EDGE* AdjList[MAX_SIZE];
EDGE* AdjList_GT[MAX_SIZE];
intVNum,ENum;
}ALGraph;
ALGraphSET;
unsigned char MARK[MAX_SIZE];
struct stack
{
int BASE[MAX_SIZE];
int top;
}VisitStack;
int _NO,Belong[MAX_SIZE],STEP1,STEP2;
int DAG_in[MAX_SIZE],DAG_out[MAX_SIZE];
void DFS(int x)
{
MARK[x] = 1;
EDGE *p = NULL;
for( p = SET.AdjList[x];p!=NULL; p = p->Next)
if(!MARK[p->adjvex]) DFS(p->adjvex);
VisitStack.BASE[VisitStack.top++] = x;
return ;
}
void DFS2(int x)
{
Belong[x] = _NO;
MARK[x] = 1;
EDGE *p = NULL;
for( p = SET.AdjList_GT[x]; p!=NULL; p = p->Next)
{
if(!MARK[p->adjvex])
DFS2(p->adjvex);
elseif(Belong[p->adjvex]!=Belong[x])
{
DAG_in[Belong[p->adjvex]]++;
DAG_out[Belong[x]]++;
}
}
}
int n,m;
int main()
{
freopen("Sample Input.txt","r",stdin);
system("Color F0");
int i,j;
EDGE *p = NULL;
while(scanf("%d%d",&n,&m)!=EOF)
{
SET.VNum= n;
SET.ENum= m;
for( i = 0; i <= n; i++) { SET.AdjList_GT[i] = NULL;SET.AdjList[i] = NULL; }
while(m--)
{
scanf("%d%d",&i,&j);
p = (EDGE*)malloc(sizeof(EDGE));
p->adjvex = j;
p->Next = SET.AdjList[i];
SET.AdjList[i] = p;
p = (EDGE*)malloc(sizeof(EDGE));
p->adjvex = i;
p->Next = SET.AdjList_GT[j];
SET.AdjList_GT[j] = p;
}
memset(MARK,0,sizeof(MARK));
VisitStack.top= 0;
for( i = 1; i <= SET.VNum; i++)
if(!MARK[i])
DFS(i);
memset(MARK,0,sizeof(MARK));
_NO = 0;
memset(Belong,0,sizeof(Belong));
memset(DAG_in,0,sizeof(DAG_in));
memset(DAG_out,0,sizeof(DAG_out));
while(VisitStack.top--)
{
if(!MARK[VisitStack.BASE[VisitStack.top]])
{
_NO++;
DFS2(VisitStack.BASE[VisitStack.top]);
}
}
STEP1 = 0;STEP2 = 0;
if(_NO==1)
printf("0\n");
else
{
for(i = 1; i <= _NO; i++)
{
if(!DAG_in[i]) STEP1++;
if(!DAG_out[i]) STEP2++;
}
printf("%d\n",MAX(STEP1,STEP2));
}
}
getch();
return 0;
}

HDU 3747 Download

发表于 2011-08-23 | 分类于 文章归档 | 阅读次数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3747

题目意思挺好理解的

不过 想了很久没想出来,最后看了大牛的代码才恍然大悟了,真觉得自己笨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
freopen("Sample Input.txt","r",stdin);
system("Color F0");
char S[55],T[55];
int i,j;
int Min,count[4],n;
while (scanf("%d",&n)!=EOF)
{
memset(count,0,sizeof(count));
scanf("%s",S);
scanf("%s",T);
for (i = 0; i < n; i++)
{
if (S[i]!=T[i])
count[0]++; //记录不同的位,对直接改变这些位需要的操作
else
count[1]++; //记录相同的位,反选一次后改变这些位
if(T[i]=='0') count[2]++; //目标序列中0的位,就是不需要选择的TV,全选后复原这些位需要的操作
}
//count[0]就是直接点击选择需要的总操作次数
count[1]++;
//count[1]为反选一次后再作选择总操作,增加一次反选操作
count[2]++;
//count[2]是全选一次后取消选择总操作,count[2]为全选后取消选择需要的操作,增加一次全选操作
count[3] = 2+n-(count[2]-1);
//n-(count[2]-1)等于需要选择看的TV总数 ,再+2表示全选反选归零后重新选择的做法
//count[0]直接选择是理所当然的做法。
//其实关键是需要考虑到,对于全选和反选,都是只是做一次的,或者各做一次。
//这个很容易可以证明,因为两次反选后对每一位来说,状态又回到原来的去,相当于多花费两次操作。
//每次全选就等于回到到第一次的全选了。
//全选之后反选归零。
//其实联想到逻辑代数里的一些关系,还是挺直观的。。。 为什么当时就没想到!!!!
Min = count[0];
for (i = 1; i < 4; i++)
Min = (count[i]<Min?count[i]:Min);
printf("%d\n",Min);
}
getch();
return 0;
}

HDU 3819 A and B Problem

发表于 2011-08-23 | 分类于 文章归档 | 阅读次数:

这两天碰到最纠结的一题!无限WA了~~~

出发点是这样的:先统计出某个字母(我是对A)的总数进行统计sum,然后只要按照sum个单位长度在数组里进行查找(注意是一段一段),找出含有A的个数最多的那一段,然后在这段中剩下的B就是所要移动的最少次数了。

这题要用O(n)级的算法,否则TLE

用count[i]表示从开始到第i个位置含有A的数量(遍历一次数组完成)

然后可根据count[i]直接计算出任何一段含有A的数量

表示正常从i开始的(sum个长度)的一段
move_tmp = count[i+sum-1]-count[i-1];

(因为序列是循环的)下面时某一段的尾端重新跑到整个序列的头部的情况

move_tmp = count[(i+sum)%len-1]+count[len-1]-count[i-1];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char S[110000];
int count[110000];
int len;
int main()
{
int T,ce;
int i,j,d;
int move_tmp;
int sum,max;
scanf("%d",&T);getchar();
for ( ce = 1; ce<=T; ce++)
{
scanf("%s",S);getchar();
len = strlen(S);
sum = 0;
memset(count,0,sizeof(count));
for (i = 0; i <len; i++)
{
if (S[i]=='A') sum++;
count[i] = sum;
}
max = count[sum-1];
i = 1;
for(i=1;i+sum<=len;i++)
{
move_tmp = count[i+sum-1]-count[i-1];
if ( move_tmp > max)
max = move_tmp;
}
for (; i < len; i++)
{
move_tmp = count[(i+sum)%len-1]+count[len-1]-count[i-1];
if ( move_tmp > max)
max = move_tmp;
}
printf("Case %d: %d\n",ce,sum-max);
}
return 0;
}

HDU 3818 A + B Problem

发表于 2011-08-23 | 分类于 文章归档 | 阅读次数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3818

给定一个菲波数序列,对它们进行合并,最后的结果要求是用最少的菲波数构成一个题目要求的数。

例如case1:
f(2)+f(2)+f(4) = f(3)+f(4) = f(5)

根据定义合并(判读两个数是否相邻的菲波数)
f(i) = f(i-1)+f(i-2) 如 f(5) = f(4)+f(3)

特殊情况当相同的两个菲波数时 form[i+1]==form[i]

例如有两个 f(a):第一个拆成f(a)=f(a-1)+f(a-2),另一个根据f(a)+f(a-1)=f(a+1)合并

所有有form[i+1]++,合并后的f(a+1) form[i]-=2 剩下的f(a-2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const int INF = 1000000;
int cmp(const void *a,const void *b) { return *(int *)a - *(int *)b;}
int main()
{
int T,ce,m,total;
int i,j,k,merge;
scanf("%d",&T);
int form[210];
for ( ce = 1; ce<=T; ce++)
{
total = 0;
scanf("%d",&m);
while ( m-- ) scanf("%d",&form[total++]);
scanf("%d",&m);
while ( m-- ) scanf("%d",&form[total++]);
qsort(form,total,sizeof(form[0]),cmp);
m = total;merge = 1;
while (merge)
{
merge = 0;
for ( i = 0; i < total; i++)
{
if (form[i]==INF)
continue;
else if( form[i]==2 && form[i+1] == 2)
{
form[i] = INF;m--;
form[i+1] = 3;
merge = 1;
qsort(form,total,sizeof(form[0]),cmp);
break;
}
else if ( form[i+1] == form[i]+1)
{
form[i+1] += 1;m--;
form[i] = INF;
merge = 1;
qsort(form,total,sizeof(form[0]),cmp);
break;
}
else if ( form[i+1]==form[i] &&form[i]!=0 && form[i] < INF)
{
form[i+1]+=1; form[i]-=2;
merge = 1;
qsort(form,total,sizeof(form[0]),cmp);
break;
}
}
}
printf("Case %d:\n",ce);
printf("%d",m);
for ( i = 0; i < total; i++)
if ( form[i] && form[i] < INF ) printf(" %d",form[i]);
printf("\n");
}
return 0;
}

HDU 3750:Guess Game

发表于 2011-08-23 | 分类于 文章归档 | 阅读次数:

题目分析:对N求折半查找的平均查找长度(ASL),数据结构都有学的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.
int main()
{
//freopen("Sample Input.txt","r",stdin);
system("Color F0");
double ASL;
int i,j,n,a;
while (scanf("%d",&n)!=EOF)
{
ASL = 0;
for ( i=1,j=1,a=1; a<=n; i++)
{
ASL += i*j*1.0/n;
j *= 2;
a = a+j;
}
ASL = ASL + i*(j-a+n)*1.0/n;
printf("%.2f\n",ASL);
}
return 0;
}

HDU 1312 Red and Black

发表于 2011-08-21 | 分类于 文章归档 | 阅读次数:

秒杀题,不用说了,DFS求出@所在位置黑方块的最大连通区域

AC Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int W,H;
int sum;
char map[50][50];
int find[50][50];
typedef struct{ int x,y;} node;
int iPlus[4] = {-1,0,1,0};
int jPlus[4] = {0,-1,0,1};
void DFS(node p)
{
int k;
find[p.x][p.y] = 1;
node next;
sum++;
for ( k = 0; k < 4; k++)
{
next.x = p.x + iPlus[k];
next.y = p.y + jPlus[k];
if ( next.x >= 1 && next.x <= H && next.y >= 1 && next.y <= W)
{
if ( map[next.x][next.y]=='.' && !find[next.x][next.y] )
DFS(next);
}
}
}
int main()
{
freopen("Sample Input.txt","r",stdin);
system("Color F0");
int i,j,k;char ch;
node stand;
while ( scanf("%d%d",&W,&H),W&&H)
{
getchar();
for ( i = 1; i <= H; i++)
{
for ( j = 1; j <= W; j++)
{
scanf("%c",&ch);
if ( ch=='@') { stand.x = i; stand.y = j;}
map[i][j] = ch;
}
getchar();
}
sum = 0;
memset(find,0,sizeof(find));
DFS(stand);
printf("%d\n",sum);
}
getch();
return 0;
}

HDU 1242:Rescue

发表于 2011-08-21 | 分类于 文章归档 | 阅读次数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3818

BFS水题,注意碰到敌人的时候要加上两个单位时间就可以了。(一直停留在使用循环队列的史前时代..)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100000
typedef struct { int x,y;} node;
typedef struct { node base[SIZE]; int front,rear;} queue;
queue Q;
void push(node e)
{
Q.base[Q.rear].x = e.x;
Q.base[Q.rear].y = e.y;
Q.rear = (Q.rear+1)%SIZE;
}
node pop()
{
node e;
e.x = Q.base[Q.front].x;
e.y = Q.base[Q.front].y;
Q.front = (Q.front + 1)%SIZE;
return e;
}
const int INF = 999999;
char map[220][220];
int N,M;
int find[220][220];
int iPlus[4] = {-1,0,1,0};
int jPlus[4] = {0,-1,0,1};
void BFS(node start)
{
int k;
Q.rear = 0;
Q.front = 0;
push(start);
node next,pre;
find[start.x][start.y] = 0;
while ( Q.rear!=Q.front )
{
pre = pop();
for ( k = 0; k < 4; k++)
{
next.x = pre.x + iPlus[k];
next.y = pre.y + jPlus[k];
if ( next.x >= 1 && next.x <= N && next.y >= 1 && next.y <= M)
{
if ( map[next.x][next.y] != '#' )
{
if (map[next.x][next.y]!='x')
{
if(find[next.x][next.y] >= find[pre.x][pre.y]+1)
{
find[next.x][next.y] = find[pre.x][pre.y]+1;
push(next);
}
}
else
{
if (find[next.x][next.y] >= find[pre.x][pre.y]+2)
{
find[next.x][next.y] = find[pre.x][pre.y]+2;
push(next);
}
}
}
}
}
}
}
int main()
{
freopen("Sample Input.txt","r",stdin);
system("Color F0");
int i,j;char ch;
node s,e;
while ( scanf("%d%d",&N,&M)!=EOF)
{
getchar();
for ( i = 1; i <= N; i++)
{
for ( j = 1; j <= M; j++)
{
scanf("%c",&ch);
if ( ch=='r') { s.x = i; s.y = j;}
if ( ch=='a') { e.x = i; e.y = j;}
map[i][j] = ch;
}
getchar();
}
for ( i = 1; i <= N; i++)
{
for (j = 1; j <= M; j++)
{
find[i][j] = INF;
}
}
BFS(s);
if (find[e.x][e.y]<INF)
printf("%d\n",find[e.x][e.y]);
else
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
getch();
return 0;
}

HDU 1241:Oil Deposits

发表于 2011-08-21 | 分类于 文章归档 | 阅读次数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1241

题目解释一下就是找出有多少块有石油的区域,就是数组中的@,这边相邻指的是是周围的八个位置。

算法就是使用DFS对区域进行标记,很水,不多说了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int m,n;
int pack;
int find[110][110];
char map[110][110];
int iPlus[8] = {-1,-1,0,-1,0,1,1,1};
int jPlus[8] = {-1,1,-1,0,1,0,-1,1};
void DFS(int i,int j)
{
int k;
int near_i,near_j;
find[i][j] = 1;
for ( k = 0; k < 8; k++)
{
near_i = i + iPlus[k];
near_j = j + jPlus[k];
if ( near_i >= 0 && near_i < m && near_j >=0 && near_j < n )
{
if(find[near_i][near_j]==0 && map[near_i][near_j]=='@')
DFS(near_i,near_j);
}
}
}
int main()
{
freopen("Sample Input.txt","r",stdin);
system("Color F0");
int i,j,k;
while ( scanf("%d%d",&m,&n), m&&n)
{
for ( i = 0; i < m; i++)
{
getchar();
scanf("%s",map[i]);
}
pack = 0;
memset(find,0,sizeof(find));
for ( i = 0; i < m; i++)
{
for ( j = 0; j < n; j++)
{
if ( map[i][j]=='@' && find[i][j]==0)
{
pack++;
DFS(i,j);
}
}
}
printf("%d\n",pack);
}
getch();
return 0;
}
1…3456

sizeoftank

54 日志
3 分类
GitHub Weibo
© 2021 sizeoftank
由 Hexo 强力驱动
|
主题 — NexT.Mist v5.1.4