原题链接
解题思路:对于每一个D-pair的D值,生成相应的组,并存放在set中,若发现重复,则直接退出,否则代表成功。
#include
#include
#include
#include
using namespace std;
#define NMAX 80
set<string> J;
char S[NMAX];
int main(void) {
while (1) {
//scanf_s("%s", S);
cin >> S;
//cout << S << strlen(S) << endl;
if (S[0] == '*') break;
for (int i = 1; i <= strlen(S); i++) {
J.clear();
for (int j = 0; j < strlen(S); j++) {
if (j + i < strlen(S)) {
string a;
a += S[j];
a += S[j + i];
if (J.count(a)) {
goto WA;
}
else J.insert(a);
}
}
}
cout << S << " is surprising." << endl;
continue;
WA:
cout << S << " is NOT surprising." << endl;
}
}
关于string类型的研究:
C++string的常用函数总结
char[] string char* 相互转化
1.关于字符串的连接问题
string a("shang jiao da");
string b = "woyao";
string c = b + a;
string d = c.append(a);//注意append会改变原来的那个字符串的值,从而导致c和d的输出值是一样的
cout << a << endl; //sheng jiao da
cout << b << endl; // woyao
cout << c << endl; //woyao shang jiao da shang jiao da
cout << d << endl; //woyao shang jiao da shang jiao da
char cur1 = 'a';
string e = b + cur1; //string连接上单个的字符是没有问题的
cout << e << endl; //woyaoa
char cur2 = 'b';
string f;
f += cur2; //会将cur2先强制转化为string类型从而避免了冲突
f += cur1;
cout << f << endl; //ba
/*这种写法能过编译但是输出的g是错误的
string g;
g= cur1 + cur2;
cout << g << endl;
*/
/*这种写法会直接报错
string g = cur1 + cur2;
*/
string a = "123";
char b[4] = "456";
char d[4] = "123";
string c = a + b;
//string e = b + d; //不能使用两个char * 会报错
cout << c << endl; //123456
2.关于初始化的问题
string s("123456");
/*---------------三个参数--------------*/
string a("123456", 3, 3); //从3开始的三个字符串
cout << a << endl;
/*---------------两个参数--------------*/
string b1("123456", 2); //代表的是前两个字符
cout << b1 << endl; //12
string b2(s, 2); //代表的是从标号为2的字符开始一直到结尾
cout << b2 << endl;//3456
3.char[] 和string 的转化
string a = "123";
char b[4] = "456";
string c = b;
//string 转char[]只能赋值实现
char d[4];
d[0] = a[0];
d[1] = a[1];
d[2] = a[2];
d[3] = a[3];
//string e = b + d; //不能使用两个char * 会报错
//或者使用
strcpy(d,a.c_str())
//string转char *不需要逐一赋值
char *m= const_cast<char*>(a.c_str());
cout << c << endl; //456
cout << d << endl; //123
cout << m << endl; //123
tip:
1.当使用cin读取一个字符串时,最后的换行符不会被读入,而且在字符串的最后会被加上一个’\0’。
原题链接
读完题目后,存在如下问题:
1.最初始化的年份是什么?
2.星期数应该如何来进行计算呢?(可不可以利用天数再模上,首先应该判断是不是闰年,然后进行天数的累加)
问题一:最开始是1年1月1日,是星期六(注意这个条件题目中并没有给出,需要 根据题意进行一个推导)
问题二:累加天数然后进行模上7,需要对于一些特殊的例子进行判断
不知道为啥的WA,感觉思路上也不存在什么具体的问题
#include
using namespace std;
int w;
int N_days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int L_days[13] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 };
int S_days[13] = { 0,31,28,31,30,31,30,31,31,19,31,30,31 };
int leap(int x) {
if (x < 1582) {
if (x % 4 == 0) return 1;
return 0;
}
else if (x == 1700) return 1;
else {
if (x % 4 == 0 && (x % 100 != 0) || x % 400 == 0) return 1;
return 0;
}
}
int cac_day(int Y, int M) {
//计算Y年M月前的所有天数
int res = 0;
int* days;
for (int i = 1; i < Y; i++) {
if (leap(i)) res += 366;
else res += 365;
}
if (leap(Y)) days = L_days;
else days = N_days;
for (int i = 1; i < M; i++) res += days[i];
//特殊情况的处理
if (Y > 1752 || (Y == 1753 && M > 3)) res -= 11;//包含特殊的1752年3月份的情况
return res;
}
int week(int x) {
if (x % 7 == 2) return 7;
if (x % 7 == 1) return 6;
else if (x % 7 == 0) return 5;
else return x % 7 - 2;
//return (x + 5) % 7;
}
int Glucky(int x) {
//最后一个工作日是星期五
int w = week(x);
if (w >= 1 && w <= 4) return 0;
else return 1;
}
int Ggood(int x) {
//第一个工作日是星期1
int w = week(x);
if (w == 1 || w==6 || w==7) return 1;
else return 0;
}
int main() {
cin >> w;
while (w--) {
int D;
int lucky = 0, good = 0;
int Ys, Ms, Ye, Me;
cin >> Ys >> Ms >> Ye >> Me;
D=cac_day(Ys,Ms);
for (int i = Ys; i <= Ye; i++) {
int* days;
if (i == 1752) days = S_days;
else if (leap(i)) days = L_days;
else days = N_days;
//注意1752年9月只有19天
for (int j = (i == Ys) ? Ms : 0; j <= (i==Ye?Me:12); j++) {
//1号是第D+1天,该月最后一天为D+days[j]
if (Glucky(D + days[j])) lucky++;
if (Ggood(D+1)) good++;
D += days[j];
}
}
cout << lucky << " " << good << endl;
}
}
原题链接
题目类型:动态规划
思路一:dfs来进行穷举
超时警告事后分析复杂度为O(20^20),所以一定会超时的。
#include
#include
using namespace std;
vector<int > L;
vector<int > W;
int C, G;
int res = 0;
void dfs(int left, int right, int position) {
if (position == G) {
if (left == right) res++;
return;
}
for (int i = 0; i < L.size(); i++) {
int cur = W[position] * L[i];
if (cur > 0) right += cur;
else left -= cur;
dfs(left, right, position + 1);
//做完dfs一定要记得恢复
if (cur > 0) right -= cur;
else left += cur;
}
}
int main() {
cin >> C >> G;
for (int i = 0; i < C; i++) {
int cur;
cin >> cur;
L.push_back(cur);
}
for (int i = 0; i < G; i++) {
int cur;
cin >> cur;
W.push_back(cur);
}
dfs(0, 0, 0);
cout << res;
}
思路二:动态规划
dp[i][j]代表的时当已经放置了第i个物品之后重量为j时的总放置数。
最大重量为7500,因此对于天平的每一个状态都进行加7500的操作,从而使得左边重的时候也能正确表示。
#include
#include
using namespace std;
vector<int > L;
vector<int > W;
int C, G;
int res = 0;
int dp[25][15005];//代表的是当已经放入第i个物品时,此时重量为j的总的个数
int main() {
cin >> C >> G;
int MaxWeight = 0;
for (int i = 0; i < C; i++) {
int cur;
cin >> cur;
L.push_back(cur);
}
MaxWeight = L[L.size() - 1];
for (int i = 0; i < G; i++) {
int cur;
cin >> cur;
W.push_back(cur);
MaxWeight += cur;
}
MaxWeight *= L[L.size() - 1];
memset(dp, 0, sizeof(dp));
//初始化dp数组
for (int i = 0; i < L.size(); i++) {
dp[0][L[i] * W[0] + 7500] = 1;
}
//动态规划求解
for (int i = 1; i < W.size(); i++) {
//对所有的重量遍历
for (int j = -MaxWeight + 7500; j <= MaxWeight + 7500; j++) {
dp[i][j] = 0;
for (int k = 0; k < L.size(); k++) {
dp[i][j] += dp[i - 1][j - (W[i] * L[k])];//注意这里不需要再加上7500了
}
}
}
cout << dp[W.size() - 1][7500];
}
复杂度分析先行。