1:有一条彩色宝石项链,是由很多种不同的宝石组成的,包括红宝石,蓝宝石,钻石,翡翠,珍珠等。有一天国王把项链赏赐给了一个学者,并跟他说,你可以带走这条项链,但是王后很喜欢红宝石,蓝宝石,紫水晶,翡翠和钻石这五种,我要你从项链中截取连续的一小段还给我,这一段中必须包含所有的这五种宝石,剩下的部分你可以带走。如果无法找到则一个也无法带走。请帮助学者找出如何切分项链才能够拿到最多的宝石。
思路:参考别人的,这种题感觉比较烦,找到一个比较好的模板。主要注意点:1,包含一个abcde的串,想要最小,也就是重复的宝石最后出现的位置到现在搜索到的位置的长度,也就是字符最后出现的一个位置,先遍历找到包含五种宝石的最长子串,然后找到前面重复宝石最后出现的位置,两个位置之间就是最小长度。简单的最后出现字符查找的应用啊。2,循环的问题可以把字符串重复两次,就不用取模来判断这些了。可以包含所有情况。
链接:https://www.nowcoder.com/questionTerminal/321bf2986bde4d799735dc9b493e0065
来源:牛客网
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
bool judgeColor(int (&index)[5]) {
for (int i = 0; i < sizeof(index) / sizeof(int); i++) {
if (!index[i])
return false;
}
return true;
}
int main() {
using namespace std;
string str;
while (getline(cin, str)) {
int len = str.size();
str += str;
int l = 0, r = 0;
int length = len;
int index[5] = { 0 };
for (int i = 0; i < len * 2; i++) {
if (str[i] - 'A' < 5) {
index[str[i] - 'A']++;
if (judgeColor(index)) {
while (index[str[l] - 'A'] != 1) {
if (str[l] - 'A' < 5) {
index[str[l] - 'A']--;
}
l++;
}
if (length > r - l + 1) {
length = r - l + 1;
}
}
}
r++;
}
cout << len - length << endl;
}
return 0;
}
2,
一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子,每隔一米就有一个,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳的更远。每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5,就代表袋鼠下一跳最多能够跳5米,如果为0,就会陷进去无法继续跳跃。河流一共N米宽,袋鼠初始位置就在第一个弹簧上面,要跳到最后一个弹簧之后就算过河了,给定每个弹簧的力量,求袋鼠最少需要多少跳能够到达对岸。如果无法到达输出-1
思路:过河问题。dp肯定能做,简单的一维dp,先来别人的。
import java.util.Scanner;
public class Main {
static int [] dp=new int [100010];
static int [] d=new int [100010];
static int inf=2000000000;
static int minValue(int n, int m){
if(n>=m)
return m;
return n;
}
public static void main(String[] args) {
Scanner r=new Scanner(System.in);
int n=r.nextInt();
for(int i=1; i<=n; i++)
d[i]=r.nextInt();
for(int i=1; i<=n+1; i++){
dp[i]=inf;
}
dp[1]=0;
d[n+1]=1;
for(int i=1; i<=n; i++){
for(int j=i+1; j<=i+d[i]&&j<=n+1; j++){
//if(d[j])
if(d[j]==0)continue;
dp[j]=minValue(dp[j], dp[i]+1);
}
}
if(dp[n+1]==inf)System.out.println("-1");
else System.out.println(dp[n+1]);
r.close();
}
}
我自己的其实差不多,但是是后面到前面dp的,先找到一步能到岸上的,再找一步能到一次到岸上的,最后看flag[0] 能不能到达,每次记录上一次的最小位置就行,后面的要都是考虑过能最小次数能到到岸上的,要不就是不能到岸上的。
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;
int main() {
int n ;
cin>>n;
vector<int> re;
int a = n;
while(a--) {
int b ;
cin>>b;
re.push_back(b);
}
vector<int> flag(n+1,0);
flag[n] = 1;
int min1 = n,min2 = n;
int count = 0, flag2 = 0;
while(1) {
min1 = min2;
for(int i = 0; i < min1; i++) {
if(flag[i] == 0&&re[i]+i>=min1){
flag[i] = 1;
if(i<min2) min2 = i;
flag2 = 1;
}
}
if(flag2 == 0) {
cout<<-1;
return 0;
}
count++;
flag2 = 0;
if(flag[0] == 1) {
cout<<count;
return 0;
}
}
return 0;
}