您的位置:首页 > 编程语言

编程练习二(动态规划)

2016-09-25 23:29 162 查看

A:zuma(记忆化搜索)

题目:

Genos recently installed the game Zuma on his phone. In Zuma there exists a line of n gemstones, the i-th of which has color ci. The goal of the game is to destroy all the gemstones in the line as quickly as possible.

In one second, Genos is able to choose exactly one continuous substring of colored gemstones that is a palindrome and remove it from the line. After the substring is removed, the remaining gemstones shift to form a solid line again. What is the minimum number of seconds needed to destroy the entire line?

Let us remind, that the string (or substring) is called palindrome, if it reads same backwards or forward. In our case this means the color of the first gemstone is equal to the color of the last one, the color of the second gemstone is equal to the color of the next to last and so on.

input

The first line of input contains a single integer n (1 ≤ n ≤ 500) — the number of gemstones.

The second line contains n space-separated integers, the i-th of which is ci (1 ≤ ci ≤ n) — the color of the i-th gemstone in a line.

output

Print a single integer — the minimum number of seconds needed to destroy the entire line.

Sample Input

Input

3

1 2 1

Output

1

Input

3

1 2 3

Output

3

Input

7

1 4 4 2 3 2 1

Output

2

我的代码:

#include <iostream>
#include <string.h>
using namespace std;

int input[505];
int dp[505][505];
int visited[505][505];
int num;

int dfs(int l, int r){
if (visited[l][r]==1) {
return dp[l][r];
}
visited[l][r] = 1;dp[l][r] = 505;
if (l > r) {
return dp[l][r] = 0;
}
if (l == r) {
return dp[l][r] = 1;
}
if (l == r-1) {
if(input[l] == input[r]){
return dp[l][r] = 1;
}else{
return dp[l][r] = 2;
}
}
if(input[l] == input[r]){
// 这里没有return
dp[l][r] = dfs(l+1, r-1);
}
for (int i = l; i <r; i++) {
dp[l][r] = min(dfs(l, i) + dfs(i+1, r),dp[l][r] );
}
return dp[l][r];
}
int main(int argc, const char * argv[]) {
cin >> num;
memset(visited, 0, sizeof(visited));

for (int i = 1; i <= num ; i++) {
cin >> input[i];
}
cout << dfs(1, num) << endl;
return 0;
}


其它参考解答:

http://blog.csdn.net/qq_21057881/article/details/51429865

B:Cyborg Genes

题目

给出两个字符串,找出第三个字符串,使得给出的两个字符串都是第三个字符串的子串,现在要求所得字符串最短,并且输出有多少种组成方法。

我的代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;

int T;

char str1[35];
char str2[35];
//最长公共子序列长度
unsigned int mcs[35][35];
//最短孩子基因序列的个数
unsigned int strnum[35][35];

int i,j;
int main() {
//freopen("input.txt", "r", stdin);
// freopen("output.txt","w", stdout);
while(scanf("%d%*c",&T)!=EOF){
for (int times = 1; times <= T; times++){
memset(mcs, 0, sizeof(mcs));
memset(strnum, 0, sizeof(strnum));
memset(str1, 0, sizeof(str1));
memset(str2, 0, sizeof(str2));
gets(str1);
gets(str2);
int len1 = strlen(str1);
int len2 = strlen(str2);
for (i = 0; i <=len1; i++) {
strnum[i][0] = 1;
}
for (i = 0; i <= len2 ; i++) {
strnum[0][i] = 1;
}
//注意这里的i,j标
for (i = 1; i <= len1; i++) {
for (j = 1; j <= len2 ; j++) {
if (str1[i-1] == str2[j-1]) {
mcs[i][j] = mcs[i-1][j-1]+1;
strnum[i][j] = strnum[i-1][j-1];
}else if(mcs[i-1][j] > mcs[i][j-1]  ){
mcs[i][j] = mcs[i-1][j];
strnum[i][j] = strnum[i-1][j];
}else if(mcs[i-1][j] < mcs[i][j-1] ){
mcs[i][j] = mcs[i][j-1];
strnum[i][j] = strnum[i][j-1];
}else{
mcs[i][j] = mcs[i-1][j];
strnum[i][j] = strnum[i-1][j] + strnum[i][j-1];
}
}

c7f2
}
printf("Case #%d: %u %u\n", times, len1 + len2 - mcs[len1][len2], strnum[len1][len2]);
}
}
return 0;
}


C:Mountain Road(dp+贪心)

参考解答:

http://blog.csdn.net/accelerator_/article/details/21259397

题目

In the Franconian Switzerland, there is a narrow mountain road. With only a single lane, this is a bottleneck for two-way traffic. Your job is to schedule incoming cars at both ends so that the last car leaves the road as early as possible.

Each car is specified by three values: the direction in which it is going, the arrival time at the corresponding beginning of the road, and the driving time this car needs to get through, provided it is not slowed down by other cars in front. Cars cannot overtake each other on the mountain road, and reordering cars in the queues at the ends of the road is not allowed.

For safety reasons, two successive cars going in the same direction may not pass any point of the road within less than 10 seconds. This ensures that the second car will not crash into the first car if the latter brakes hard. However, if another car passes in the other direction in between, it will be clear that the road is empty, so in this case, this rule does not apply.

Input

The first line of the input consists of a single integer c (1 ≤ c ≤ 200), the number of test cases.

Then follow the test cases, each beginning with a single line consisting of an integer n (1 ≤ n ≤ 200), the number of cars you are to consider in this test case. The remainder of each test case consists of nlines, one line per car, starting with a single upper case letter (“A” or “B”), giving the direction in which the car is going. Then follow, on the same line, two integers t (0 ≤ t ≤ 100000) and d (1 ≤ d ≤100000), giving the arrival time at the beginning of the road and the minimum travel time, respectively, both in seconds.

Within a test case, the cars are given in order of increasing arrival time, and no two cars will arrive at the same time.

Output

For each test case, print a single line consisting of the point in time (in seconds) the last car leaves the road when the cars are scheduled optimally.

Sample Input Sample Output

2

4

A 0 60

B 19 10

B 80 20

A 85 100

4

A 0 100

B 50 100

A 100 1

A 170 100

200

270

题意:

A,B两点,给定n辆车,A,B为车的目的地,t为发车时间,d为最快的路程花费的时间。由于要确保安全,要满足一下两个条件:

1、不能有反方向的车

2、相同方向的车之间时间不能相差小于10秒。

问所有汽车最小需要的时间。

思路:

先是贪心的思想,方向相同放在一起,发车时间小的肯定是先发最优。题目给定的已经是升序了,所以无需排序。

然后是DP,把A和B方向车分开存,dp[i][j][d]代表的是前i辆A车,j辆B车,最后一辆方向为d,需要的最少时间。方向A为0,B为1

这样由dp[i][j][0]这个状态可以往后选x辆B,dp[i][j][1]这个状态可以往后选x辆A,起始时间为dp[i][j] dp[k]j = min{time};

time的求法为从起始时间开始确定,每次维护起始时间和到达时间即可,注意由于间隔要大于10,所以最后后面要+10.

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int T,n;
int i, j;
char direction[2];
struct info{
int start;
int t;
};

info ax[205];
info bx[205];
int dp[205][205][2];
int a,b;
int numa = 1;//总数+1
int numb = 1;
int func(){
memset(dp, INF, sizeof(dp));
int s,e;
s = e = 0;
dp[0][0][0] = dp[0][0][1] = 0;
for (i = 0; i < numa ; i++) {
for (j = 0; j < numb; j++) {
s = dp[i][j][1];
e= 0;
int k;
for (k = i + 1; k < numa; k++) {
s = max(s, ax[k].start);
e = max(s + ax[k].t, e);
dp[k][j][0] = min(dp[k][j][0], e);
s += 10; e += 10;
}
s = dp[i][j][0]; e = 0;
for (k = j + 1; k < numb; k++) {
s = max(s, bx[k].start);
e = max(s + bx[k].t, e);
dp[i][k][1] = min(dp[i][k][1], e);
s += 10; e += 10;
}
}
}
return min(dp[numa-1][numb-1][0], dp[numa-1][numb-1][1]);
}
int main() {
// freopen("input.txt", "r", stdin);
//freopen("output.txt","w", stdout);
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
memset(ax,0,sizeof(ax));
memset(bx,0, sizeof(bx) );
for (i = 0; i < n; i++) {
scanf("%s", direction);
if (direction[0] == 'A') {
scanf("%d %d",&ax[numa].start, &ax[numa].t );
numa++;
}else{
scanf("%d %d",&bx[numb].start, &bx[numb].t );
numb++;
}
}
printf("%d\n", func());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 编程