1001:A+B Format (20 分)(AC:stack)
注意要点:
1.注意0的时候的问题。
#include<iostream>
#include<stack>
using namespace std;
stack<char> s;
int main(){
int a , b , count = 0 , n = 0;
scanf("%d %d" , &a , &b);
int t = a + b;
//全是对于t的正数操作//
if(t < 0){
t = -t;
}
//对于 t 的处理//
while(t != 0){
char c = t % 10 + '0';
s.push(c);
count ++;
if(count == 3){
s.push(',');
count =0;
}
t /= 10;
}
//判断正负//
if(a + b < 0){
printf("-");
}
if(a + b == 0){
printf("0");
return 0;
}
//输出//
while(!s.empty()){
if(n == 0 && s.top() == ','){
s.pop();
n ++;
continue;
}
printf("%c" , s.top());
s.pop();
n ++;
}
return 0;
}
1002:A+B for Polynomials (25)(AC)
注意要点:
1.float数组类型初始化的时候切记内部数字也得是0.0,要不然真的死都不知道怎么死的。
2.多组数据只要是后面不用的,都可以共用一个。
#include<iostream>
using namespace std;
int main() {
int M;
int a;
float b;
int num = 0;
float p[1005] = {0.0} ; //注意这个地方//
scanf("%d" , &M);
//第一行//
for(int i = 0 ; i < M ; i ++) {
scanf("%d %f" , &a , &b);
p[a] += b ;
}
//第二行//
getchar();
scanf("%d" , &M);//可以直接覆盖//
for(int i = 0 ; i < M ; i ++) {
scanf("%d %f" , &a , &b);
p[a] += b; //在第一行基础之上往上加//
}
//统计个数//
for(int i = 0 ; i < 1005 ; i ++){
if(p[i] != 0) num ++;
}
printf("%d" , num);
for(int i = 10 ; i >= 0 ; i --){
if(p[i] != 0)
printf(" %d %.1f" , i , p[i]);
}
return 0;
}
1003:Emergency (25 分)(AC)
注意要点:
1.Dijkstra + BFS
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXV = 505;
const int INF = 1000000;
int G[MAXV][MAXV] , num[MAXV] , w[MAXV] , d[MAXV] , weight[MAXV];
int N , M , S , D;
bool vis[MAXV] = { 0 };
void Dijkstra(int S){
//初始化//
fill(d , d + MAXV , INF);
memset(w , 0 , sizeof(w));
memset(num , 0 , sizeof(num));
//开始各种标记//
d[S] = 0;
w[S] = weight[S];
num[S] = 1;
//遍历每个点//
for(int i = 0 ; i < N ; i ++) {
//找到d之中最小的//
int u = -1 , MIN = INF;
for(int j = 0 ; j < N ; j ++){
if(vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
}
//特殊情况找不到,退出//
if(u == -1) return ;
vis[u] = true;
//修改值//
for(int v = 0 ; v < N ; v ++) {
if(vis[v] == false && G[u][v] != INF){
if(d[u] + G[u][v] < d[v]){
d[v] = d[u] + G[u][v];
w[v] = w[u] + weight[v];
num[v] = num[u];
}
else if(d[u] + G[u][v] == d[v]){
if(w[u] + weight[v] > w[v])
w[v] = w[u] + weight[v];
num[v] += num[u];
}
}
}
}
}
int main() {
int a , b , c;
scanf("%d %d %d %d" , &N , &M , &S , &D);
for(int i = 0 ; i < N ; i ++) {
scanf("%d" , &weight[i]);//救援队既是权值//
}
fill(G[0] , G[0] + MAXV * MAXV , INF);
for(int i = 0 ; i < M ; i ++) {
scanf("%d %d %d" , &a , &b , &c);
G[a][b] = c;
G[b][a] = c;
}
Dijkstra(S);
printf("%d %d\n" , num[D] , w[D]);
return 0;
}
1004:Counting Leaves (30 分)(AC:DFS)
注意要点:
1.一开始的思路是去建立一棵树,想了想发现DFS也可以做出来。
2.强化DFS问题解决方式:递归 + 边界判断。
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 105;
vector<int> v[MAXN];
int J[MAXN];
int D = -1;
void DFS(int x , int depth){
//边界//
if(v[x].size() == 0){
J[depth] ++;
D = max(depth , D);
return ;
}
//递归//
for(int i = 0 ; i < v[x].size() ; i ++){
DFS(v[x][i] , depth + 1);
}
}
int main(){
int N , M , ID , K , a;
//输入//
scanf("%d %d" , &N , &M);
for(int i = 0 ; i < M ; i ++){
scanf("%d %d" , &ID , &K);
for(int j = 0 ; j < K ; j ++){
scanf("%d" , &a);
v[ID].push_back(a);
}
}
//DFS//
DFS(1 , 0);
//输出//
for(int i = 0 ; i <= D ; i ++){
if(i == 0){
printf("%d" , J[i]);
}
else{
printf(" %d" , J[i]);
}
}
return 0;
}
1005:Spell It Right (20 分)(AC:Vector)
注意要点:
1.0的情况考虑一下。
#include<iostream>
#include<vector>
using namespace std;
vector<int> v;
int main(){
int sum = 0 ;
char a;
char b[10][10] = {"zero" , "one" , "two" , "three" , "four" , "five" , "six" , "seven" , "eight" , "nine"};
//输入//
while(scanf("%c" , &a) == 1){
if(a != '\n')
sum =sum + (a - '0');
}
//倒着插入//
if(sum == 0){
printf("zero");
}
else{
while(sum != 0){
int c = sum % 10;
v.push_back(c);
sum /= 10;
}
//输出//
for(int i = v.size() - 1 ; i >= 0 ; i --){
if(i == v.size() - 1){
printf("%s" , b[v[i]]);
}
else{
printf(" %s" , b[v[i]]);
}
}
}
return 0;
}
1007:Maximum Subsequence Sum (DP)
掌握了一个基本的dp问题的思路。
先写边界,随后确定递推公式。基本的模型一定要先理解清楚,随后做题才能在此基础之上进一步求解。
#include<iostream>
using namespace std;
const int MAXN = 10005;
int main(){
int K;
int a[MAXN] , dp[MAXN];//dp的含义是指,在这个数值状态下的最大的数值是多少//
int s[MAXN] = { 0 };
bool flag = true;
scanf("%d" , &K);
for(int i = 0 ; i < K ; i ++){
scanf("%d" , &a[i]);
if(a[i] >= 0){
flag = false;
}
}
if(flag == true){//如果有一个数字是负数的话,则直接输出//
printf("%d %d %d" , 0 , a[0] , a[K - 1]);
return 0;
}
dp[0] = a[0];//第一个数值就是其本身//
for(int i = 1 ; i < K ; i ++){
if(dp[i - 1] + a[i] > a[i]){ //
dp[i] = dp[i - 1] + a[i];
s[i] = s[i - 1];
}
else{
dp[i] = a[i];
s[i] = i;
}
}
int n = 0;
for(int i = 1 ; i < K ; i ++){
if(dp[i] > dp[n]){
n = i;
}
}
printf("%d %d %d\n" , dp[n] , a[s[n]] , a[n]);
return 0;
}
1008:Elevator (20 分)(AC:vector数学问题)
注意要点:
无。
#include<iostream>
#include<vector>
using namespace std;
vector<int> v;
int main(){
int N , a , d = 0;
//输入//
scanf("%d" , &N);
for(int i = 0 ; i < N ; i ++){
scanf("%d" , &a);
v.push_back(a);
}
//层数操作//
for(int i = 0 ; i < v.size() ; i ++){
//一层//
if(i == 0){
d = d + (v[i] - 0) * 6 + 5;
}
//二层以上 , 比你高//
else if( i != 0 && (v[i] > v[i - 1])){
d = d + ((v[i] - v[i - 1]) * 6 + 5);
}
// 二层以上,比你低//
else{
d = d + ((v[i - 1] - v[i]) * 4 + 5);
}
}
printf("%d" , d);
return 0;
}
1009:Product of Polynomials (25 分)(AC:数学模拟)
注意要点:
1.审题,注意这个题目是要求乘法,我一开始做成加法了, 浪费了很多时间。
2.double类型只能由lf来接,否则都是根本接不到。
3.这个题思路也是很清晰,几乎不用拐弯,我开了两个数组的原因是不想交叉起来不好修改。
#include<iostream>
using namespace std;
int main(){
int N , M , a , c , maxn = -1 , count = 0;
double b , d;
double A[10000] = { 0 } , B[10000] = { 0 };
//输入//
scanf("%d" , &N);
for(int i = 0 ; i < N ; i ++){
scanf("%d %lf" , &a , &b);
A[a] = A[a] + b;
//边界//
if(a > maxn){
maxn = a;
}
}
scanf("%d" , &M);
for(int j = 0 ; j < M ; j ++){
scanf("%d %lf" , &c , &d);
//换到B数组里面//
for(int i = maxn ; i >= 0 ; i --){
if(A[i] != 0){
B[i + c] = B[i + c] + d * A[i];
if(i + c > maxn){
maxn = i + c;
}
}
}
}
for(int i = 0 ; i <= maxn ; i ++){
if(B[i] != 0){
count ++;
}
}
//输出//
printf("%d " , count);
for(int i = maxn ; i >= 0 ; i --){
if(B[i] != 0.0){
printf("%d %.1lf" , i , B[i]);
count --;
if(count > 0)
printf(" ");
}
}
return 0;
}
1011:World Cup Betting (20 分)(AC:数学模拟)
注意要点:
1.这个输出着实牛啤,还能这么输出。
#include<iostream>
using namespace std;
int main(){
float a, sum = 1 ;
int k;
char S[3] = {'W' , 'T' , 'L'};//对应字符表//
//输入//
for(int i = 0 ; i < 3 ; i ++){
float max = -1.0 ;
for(int j = 0 ; j < 3 ; j ++){
scanf("%f" , &a);
if(a > max){
max = a;
k = j;
}
}
printf("%c " , S[k]);
sum *= max;
}
//输出2//
printf("%.2f" , (sum * 0.65 - 1) * 2);
return 0;
}
1013:Battle Over Cities (25 分)(AC :DFS , 并查集)
注意要点:
1.dfs之后改用连接表,不要使用图了。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int INF = 10000000;
vector<int> v[1005];
int c;
bool vis[1005];
void dfs(int e){
if(e == c) return ;
vis[e] = true;
for(int i = 0 ; i < v[e].size() ; i ++){
if(vis[v[e][i]]== false){
dfs(v[e][i]);
}
}
}
int main(){
int N , M , K ,a , b;
//输入//
scanf("%d %d %d" , &N , &M , &K);
for(int i = 0 ; i < M ; i ++){
scanf("%d %d" , &a , &b);
v[a].push_back(b);
v[b].push_back(a);
}
//输出//
for(int i = 0 ; i < K ; i ++){
scanf("%d" , &c);
memset(vis , false , sizeof(vis));
int block = 0;
for(int i = 1 ; i <= N ; i ++){
if(i != c && vis[i] == false){
dfs(i);
block ++;
}
}
printf("%d\n" , block - 1);
}
return 0;
}
1020:Tree Traversals (25 分)(AC)
注意要点:
2.这个层序遍历的这个地方非常容易错,修改了两三次才AC了。
#include<iostream>
#include<queue>
using namespace std;
struct node{
int data;
node* lchild;
node* rchild;
};
int pos[55] , in[55];
int N;
//利用后根数列和中根数列求原来的数列//
node* creat(int posL , int posR , int inL , int inR) {
//边界//
if(posL > posR){
return NULL;
}
//求根节点//
node* root = new node;
root->data = pos[posR];
int k;
for(k = inL ; k <= inR ; k ++) {
if(in[k] == pos[posR])
break;
}
//左右分支//
int numleft = k - inL;
root->lchild = creat(posL , posL + numleft - 1 , inL , k - 1);//易错//
root->rchild = creat(posL + numleft , posR - 1, k + 1 , inR);
return root;
}
//利用BFS来输出这个层序遍历。//
int num = 0 ;
void BFS(node* root) {
queue<node*> q;
q.push(root);
while(!q.empty()){
node* t = q.front();
q.pop();
printf("%d" , t->data);
num ++;
if(num < N) printf(" ");
if(t->lchild != NULL) q.push(t->lchild);
if(t->rchild != NULL) q.push(t->rchild);
}
}
int main() {
scanf("%d" , &N);
for(int i = 0 ; i < N ; i ++) {
scanf("%d" , &pos[i]);
}
for(int i = 0 ; i < N ; i ++) {
scanf("%d" , &in[i]);
}
node* root = creat(0 , N - 1 , 0 , N - 1);
BFS(root);
return 0;
}
1030:Travel Plan (30 分)(AC:Dijkstra第二形态 + 记忆化DFS)
注意要点:
1.这个地方注意这是个无向图。需要注意来回的数值都可以。
2.巧了,不知道为什么PTA的数值题目都可以用 Matrix 来做。看来数据还是小。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN = 505;
const int INF = 100005;
//初始化定义//
int G[MAXN][MAXN];
int cost[MAXN][MAXN];
int d[MAXN] , x[MAXN];
int pre[MAXN];
bool vis[MAXN];
int N , M , S , D;
int a , b , c , de;
void Dijkstra(int s){
fill(d , d + MAXN , INF);
fill(x , x + MAXN , INF);
//Ñ°ÕÒÇ°Çý½áµã//
for(int i = 0 ; i < N ; i ++){
pre[i] = i;
}
d[s] = 0;
x[s] = 0;
for(int i = 0 ; i < N ; i ++){
int u = -1 , MIN = INF;
//第一步:找最小值//
for(int j = 0 ; j < N ; j ++){
if(vis[j] == false && d[j] < MIN){
MIN = d[j];
u = j;
}
}
//第二步:确定范围//
if(u == -1) return ;
//第三步:更新数值//
vis[u] = true;
for(int v = 0 ; v < N ; v ++){
if(vis[v] == false && G[u][v] != INF){
if(d[u] + G[u][v] < d[v]){
d[v] = d[u] + G[u][v];
x[v] = x[u] + cost[u][v];
pre[v] = u;
}
else if(d[u] + G[u][v] == d[v]){
if(x[u] + cost[u][v] < x[v]){
x[v] = x[u] + cost[u][v];
pre[v] = u;
}
}
}
}
}
}
//记忆化搜索//
void DFS(int v){
if(v == S){
printf("%d " , S);
return ;
}
DFS(pre[v]);
printf("%d " , v);
}
int main(){
//初始化数据//
fill(d , d + MAXN , false);
fill(G[0] , G[0] + MAXN * MAXN , INF);
//ÊäÈë//
scanf("%d %d %d %d" , &N , &M , &S , &D);
for(int i = 0 ; i < M ; i ++){
scanf("%d %d %d %d" , &a , &b , &c , &de);
G[a][b] = c;
G[b][a] = c;
cost[a][b] = de;
cost[b][a] = de;
}
//最短路径//
Dijkstra(S);
//输出//
DFS(D);
printf("%d %d\n" , d[D] , x[D]);
}
1031:Hello World for U (20 分)(AC:打印图案)
思路提示:
1.首先需要确定n1 , n2 , n3的数值,其次按照边框再每一个打印出来,最后二维数组写出。
注意要点:
1.最后强调一次这个memset这个功能。在cstring头文件下。
#include<iostream>
#include<cstring>
using namespace std;
int main(){
char s[100];
char m[100][100];
memset(m , ' ' , sizeof(m));
scanf("%s" , s);
//确定n1 , n2 , n3 //
int len = strlen(s) + 2;
int n1 = len / 3;
int n3 = n1;
int n2 = len / 3 + len % 3;
//填入数组中//
int k = 0 ;
for(int i = 0; i < n1 ; i ++){//n1//
m[i][0] = s[k ++];
}
for(int i = 1 ; i <= n2 - 2 ; i ++){//n2//
m[n1 - 1][i] = s[k ++];
}
for(int i = n3 - 1 ; i >= 0 ; i --){//n3//
m[i][n2 - 1] = s[k ++];
}
//输出//
for(int i = 0 ; i < n1 ; i ++){
for(int j = 0 ; j < n2 ; j ++){
printf("%c" , m[i][j]);
}
printf("\n");
}
return 0;
}
1033:Sharing (25 分)(AC:模拟链表)
思路提示:
1.模拟链表的技巧。
注意要点:
%05d,超容易犯错。
#include<iostream>
const int MAXN = 100005;
using namespace std;
struct node{
char data;
int next;
}Node[MAXN];
int main(){
int s1 , s2 , n , a , c , k = 0;
char b;
bool L[MAXN] = { false };
//输入//
scanf("%d %d %d" , &s1 , &s2 , &n);
for(int i = 0 ; i < n ; i ++){
scanf("%d %c %d" , &a , &b , &c);
Node[a].data = b;
Node[a].next = c;
}
//第一轮//
int root = s1;
while(root != -1){
L[root] = true;
root = Node[root].next;
}
L[root] = true;
//第二轮:找交点//
int root2 = s2;
while(root2 != -1){
if(L[root2] == true){
printf("%05d" , root2);
L[root2] = false;//防止下次判断//
break;
}
root2 = Node[root2].next;
}
if(L[root2] == true)
printf("-1");
return 0;
}
1035:Password (20 分)(AC::水题)
思路提示:请认真读题。
注意要点:
1.这个地方注意这个多数和单一的情况。
#include<iostream>
#include<cstring>
using namespace std;
struct A{
string b;//第一个字符串//
string c;//第二个字符串//
bool flag;//判断这个是否修改过//
}a[1005];
int main(){
int n , count = 0;
scanf("%d" , &n);
for(int i = 0 ; i < n ; i ++){
cin >> a[i].b >> a[i].c;
for(int j = 0 ; j < a[i].c.size() ; j ++){//不停的进行修改保存//
if(a[i].c[j] == '1'){
a[i].c[j] = '@';
a[i].flag = 1;
continue;
}
if(a[i].c[j] == '0'){
a[i].c[j] = '%';
a[i].flag = 1;
continue;
}
if(a[i].c[j] == 'l'){
a[i].c[j] = 'L';
a[i].flag = 1;
continue;
}
if(a[i].c[j] == 'O'){
a[i].c[j] = 'o';
a[i].flag = 1;
continue;
}
}
if(a[i].flag == 1){
count ++;//有问题个数的统计//
}
}
//输出//
if(n == 1 && count == 0){//1的情况//
printf("There is 1 account and no account is modified");
}
else if(count == 0){//多数的情况//
printf("There are %d accounts and no account is modified" , n);
}
else{//输出错误的情况//
printf("%d\n" , count);
for(int i = 0 ; i < n ; i ++){
if(a[i].flag == 1){
cout << a[i].b << " " << a[i].c;
count --;
if(count != 0){
printf("\n");
}
}
}
}
return 0;
}
1036:Boys vs Girls (25 分)(AC :水题)
注意要点:注意读题,缺的地方写Absent。
#include<iostream>
#include<cstring>
#include<math.h>
using namespace std;
int main(){
int n , maxm = 10000 , maxn = -1 ;
string maxmID , maxmname , maxnID , maxnname;
scanf("%d" , &n);
for(int i = 0 ; i < n ; i ++){
int number;
char sex ;
string ID , name;
cin >> name >> sex >> ID >> number;
if(sex == 'M' && maxm > number){//成绩为男性//
maxmname = name;
maxmID = ID;
maxm = number;
}
if(sex == 'F' && maxn < number){//成绩为女性//
maxnname = name;
maxnID = ID;
maxn = number;
}
}
//输出//
if(maxm == 10000 || maxn == -1){//缺一个//
if(maxm == 10000)
cout << maxnname << " " << maxnID << endl << "Absent" << endl << "NA";
if(maxn == -1)
cout << "Absent" << endl << maxmname << " " << maxmID << endl << "NA";
}
else{//全有//
cout << maxnname << " " << maxnID << endl;
cout << maxmname << " " << maxmID << endl;
printf("%d" , abs(maxn - maxm));
}
return 0;
}
1040:Longest Symmetric String (25 分)(AC:DP)
注意要点:控制每次移动的长度,从1-3。
#include<iostream>
#include<cstring>
using namespace std;
int dp[1005][1005];
int main(){
string s;//注意小写string//
int ans = 1;
getline(cin , s);//专用空格//
int len = s.size();
memset(dp , 0 , sizeof(dp));//长度为 1和 2 的情况//
for(int i = 0 ; i < len ; i ++){
dp[i][i] = 1;
if(i < len - 1){
if(s[i] == s[i + 1]){
dp[i][i + 1] = 1;
ans = 2;
}
}
}
//处理数据长度为3//
for(int L = 3 ; L <= len ; L ++){
for(int i = 0 ; i + L - 1 < len ; i ++){
int j = i + L - 1;//记录末尾值//
if(s[i] == s[j] && dp[i + 1][j - 1] == 1){
dp[i][j] = 1;
ans = L;
}
}
}
printf("%d" , ans);
return 0;
}
1043:Is It a Binary Search Tree (25 分)(AC)
注意要点:
这个题目非常好,典型的二叉搜索树的体现。操作类似于树的操作。
#include<iostream>
#include<vector>
using namespace std;
struct node{
int data;
node *left;
node *right;
};
void insert(node* &root , int a) {
if(root == NULL){
root = new node;
root->data = a;
root->left = NULL;
root->right = NULL;
return ;
}
if(a < root->data) insert(root->left , a);
else insert(root->right , a);
}
void preorder(node* root , vector<int>&v){
if(root == NULL){
return ;
}
v.push_back(root->data);
preorder(root->left , v);
preorder(root->right , v);
}
void preorderM(node* root , vector<int>&v){
if(root == NULL){
return ;
}
v.push_back(root->data);
preorderM(root->right , v);
preorderM(root->left , v);
}
void postorder(node* root , vector<int>&v){
if(root == NULL){
return ;
}
postorder(root->left , v);
postorder(root->right , v);
v.push_back(root->data);
}
void postorderM(node* root , vector<int>&v){
if(root == NULL){
return ;
}
postorderM(root->right , v);
postorderM(root->left , v);
v.push_back(root->data);
}
vector<int>origin , pre , preM , post , postM;//初始, 前序 , 后序 , 平衡前序 , 平衡后序//
int main() {
int N , a;
node *root = NULL;
//输入//
scanf("%d" , &N);
for(int i = 0 ; i < N ; i ++) {
scanf("%d" , &a);
origin.push_back(a);
insert(root , a);
}
//前序//
preorder(root , pre);
//镜像前序//
preorderM(root , preM);
//后序//
postorder(root , post);
//镜像后序//
postorderM(root , postM);
if(origin == pre){
printf("YES\n");
for(int i = 0 ; i < post.size() ; i ++) {
if(i == post.size() - 1)
printf("%d" , post[i]);
else
printf("%d " , post[i]);
}
}
else if(origin == preM){
printf("YES\n");
for(int i = 0 ; i < postM.size() ; i ++) {
if(i == postM.size() - 1)
printf("%d" , postM[i]);
else
printf("%d " , postM[i]);
}
}
else{
printf("NO\n");
}
return 0;
}
1045:Favorite Color Stripe(LCS)
这个题目其实LIS也是可以做的,但是我没有做。以后有时间补上。
一开始我还在想这个地方会不会有冲突出现,但是一想,LCS已经完美的解决了这个问题,关键是这个地方他有个重复的问题在里面。当前的状态如果没有匹配到的话,那就直接把前面的数值补进来。
#include<iostream>
using namespace std;
const int MAXM = 205;
const int MAXL = 10005;
int a[MAXM] , b[MAXL] , dp[MAXM][MAXL];//这个要定义到外面,内部空间不够会报错.dp表示当前的最大的数值//
int main(){
int n , m , l;
scanf("%d" , &n);
scanf("%d" , &m);
for(int i = 1 ; i <= m ; i ++){
scanf("%d" , &a[i]);
}
scanf("%d" , &l);
for(int i = 1 ; i <= l ; i ++){
scanf("%d" , &b[i]);
}
//边界//
for(int i = 0 ; i <= m ; i ++){
dp[i][0] = 0;
}
for(int i = 0 ; i <= l ; i ++){
dp[0][i] = 0;
}
//递推//
for(int i = 1 ; i <= m ; i ++){
for(int j = 1 ; j <= l ; j ++){
if(a[i] == b[j]){
dp[i][j] = max(dp[i - 1][j] , dp[i][j - 1]) + 1;
}
else{
dp[i][j] = max(dp[i - 1][j] , dp[i][j - 1]);
}
}
}
printf("%d\n" , dp[m][l]);
return 0;
}
1047:Student List for Course(25 分)(AC)
注意要点:
1.这个地方因为不需要输入名字,所以不用hash了。
2.注意字典序的用法。
3.这个地方C的写法。二维数组换成了几个一维数组字符串。
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
char C[40005][5];
vector<int> course[40005];
bool cmp(int a , int b) {
return strcmp(C[a] , C[b]) < 0 ;//这个地方注意字典序的排列//
}
int main(){
int N , K;
int c , d;
scanf("%d %d" , &N , &K);
for(int i = 0 ; i < N ; i ++) {
scanf("%s %d" , C[i] , &c);
for(int j = 0 ; j < c ; j ++) {
scanf("%d" , &d);
course[d].push_back(i);
}
}
//输出//
for(int i = 1 ; i <= K ; i ++) {
printf("%d %d\n" , i , course[i].size());
sort(course[i].begin() , course[i].end() , cmp);
for(int j = 0 ; j < course[i].size() ; j ++) {
printf("%s\n" , C[course[i][j]]);
}
}
return 0;
}
1053:Path of Equal Weight (30 分)(AC)
注意要点:
1.一开始这个路径这个地方需要设置开头的点为0。
2.注意每次实现完之后都要return (因为 return 的是上一级)。
3.这个地方记录一下这个path的问题。其实path本身并不是完全记录每一条的路径。他其实就是一个再覆盖。
本身的地方在于这个输出。这个输出如果对了,就打印在他前面的所有节点的数据就可以了,而他后面的数据则不用管。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int N , M , S , path[105];
struct node{
int weight;
vector<int> child;
}Node[105];
bool cmp(int a , int b){
return Node[a].weight > Node[b].weight;
}
void DFS(int index , int num , int sum){
if(sum > S) return ;//超了//
else if(sum == S){//正好//
if(Node[index].child.size()!= 0)
return ;
for(int i = 0 ; i < num ; i ++){
if(i == num - 1)
printf("%d\n" , Node[path[i]].weight);
else
printf("%d " , Node[path[i]].weight);
}
}
else{//不够//
for(int i = 0 ; i < Node[index].child.size() ; i ++){
int c= Node[index].child[i];
path[num] = c;//这个地方其实是直接覆盖的。
DFS(c , num + 1 , sum + Node[c].weight);
}
}
}
int main(){
scanf("%d %d %d" , &N , &M , &S);
for(int i = 0 ; i < N ; i ++){
scanf("%d" , &Node[i].weight);
}
for(int i = 0 ; i < M ; i ++){
int id , num , a;
scanf("%d %d" , &id , &num);
for(int j = 0 ; j < num ; j ++){
scanf("%d" , &a);
Node[id].child.push_back(a);
}
sort(Node[id].child.begin() , Node[id].child.end() , cmp);
}
path[0] = 0;//把id放进来//
DFS(0 , 1 , Node[0].weight);//起始点的位置数码 , 当前的元素的个数,当前元素的和//
return 0;
}
1063:Set Similarity(25 分)(AC)
注意要点:
1.注意输入的时候会出点问题,尽可能的分开输入的格式。
#include<iostream>
#include<set>
using namespace std;
set<int> a[55];
void fun(int b , int c) {
int samenum = 0 , allnum = a[c].size();
for(set<int>::iterator it = a[b].begin() ; it != a[b].end() ; it ++) {
if(a[c].find(*it) != a[c].end()) samenum ++;
else allnum ++;
}
printf("%.1f%%\n" , samenum * 100.0 / allnum);
}
int main() {
int N , n , v;
int c , b;
int e ;
scanf("%d" , &N);
for(int i = 1 ; i <= N ; i ++) {
scanf("%d" , &n);
for(int j = 0 ; j < n ; j ++) {
scanf("%d" , &v);
a[i].insert(v);
}
}
//输入//
scanf("%d" , &e);
for(int i = 0 ; i < e ; i ++) {
scanf("%d %d" , &b , &c);
fun(b , c);
}
return 0;
}
1065:A+B and C (64bit) (20)(AC)
注意要点:
1。注意 long long 的写法,范围是(2 ^ - 63 , 2 ^ 63),这个一但求和值必然会超出 long long ,只需要考虑溢出的情况即可。
2。关于溢出,这个东西就是个环形的问题 ,数字超过范围符号变化到但是数字照样加,所以会出现负数的情况。所以你也可以理解,一旦两个正数加成负数必然是溢出,到那时你c的数值必不可能会超过 long long 。与此相反,另外一面情况也可以理解了。
#include<iostream>
using namespace std;
int main() {
int N;
int numcase = 1;
scanf("%d" , &N);
for(int i = 0 ; i < N ; i ++) {
long long a , b , c;
scanf("%lld%lld%lld", &a , &b , &c);
long long r = a + b;
bool flag ;
//溢出情况检查//
if(a > 0 && b > 0 && c < 0) flag = true;
else if(a < 0 && b < 0 && c >= 0) flag = false;
//正常情况检查//
else if(r > c) flag = true;
else flag = false;
//输出//
if(flag == true) {
printf("Case #%d: true\n" , numcase ++);
}
else {
printf("Case #%d: false\n" , numcase ++);
}
}
return 0;
}
1068:Find More Coins(01背包 + 记忆化搜索)
注意要点:注意01背包的含义,前i个硬币恰好有v元可以买到东西。
其次是记忆化搜索。每个状态的时候就会更新这个状态下的硬币的情况,用flag来确定每个硬币的使用情况。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 10005;
const int MAXM = 105;
int v[MAXN] , dp[MAXM];//dp的意思是指在前i个硬币恰好有v元能获得的价值//
bool flag[MAXN] , choice[MAXN][MAXM];
//在这个地方的价格和体积是一样的,所以二者合并起来了//
bool cmp(int a , int b){//因为这个题目是一个01背包,倒着输出//
return a > b;
}
int main(){
memset(dp , 0 , sizeof(dp));
int N , M;
scanf("%d %d" , &N , &M);
for(int i = 1 ; i <= N ; i ++){
scanf("%d" , &v[i]);
}
sort(v + 1 , v + N + 1 , cmp);//从1开始的sort的写法//
//状态转移方程//
for(int i = 1 ; i <= N ; i ++){
for(int V = M ; V >= v[i] ; V --){//这个地方的V已经代表了所有的情况了//
if(dp[V] <= dp[V - v[i]] + v[i]){
dp[V] = dp[V - v[i]] + v[i];
choice[i][V] = 1;//使用了一枚硬币//
}
else choice[i][V] = 0;//没有使用一枚硬币//
}
}
if(dp[M] != M){
printf("No Solution");
}
else{
//记录整个路径//
int k = N , num = 0 , c = M;
while(k >= 0){
if(choice[k][c] == 1){//如果说第k个状态下使用了//
flag[k] = true;//该种硬币标记为已经使用过了//
c = c - v[k];//价值减少//
num ++;
}
else{
flag[k] = false;//没有就标记没有//
}
k --;//往前翻//
}
//输出//
for(int i = N ; i >= 1 ; i --){
if(flag[i] == true){
printf("%d" , v[i]);
num --;
if(num > 0) printf(" ");
}
}
}
return 0;
}
1069:The Black Hole of Numbers(20 分)(AC)
注意要点:
1.sort的写法.
#include<iostream>
#include<algorithm>
using namespace std;
int a[5] = { 0 };
bool cmp(int a , int b) {
return a > b ;
}
void isarray(int N ) {
for(int i = 0 ; i < 4 ; i ++) {
a[i] = N % 10;
N /= 10;
}
}
int isnumber(int A[]) {
int sum = 0;
for(int i = 0 ; i < 4 ; i ++) {
sum = sum * 10 + a[i];
}
return sum;
}
int main() {
int N , min , max;
scanf("%d" , &N);
while(1) {
isarray(N);
sort(a , a + 4);
min = isnumber(a);//最小值//
sort(a , a + 4 , cmp);
max = isnumber(a); //最大值//
N = max - min ;
printf("%04d - %04d = %04d\n" , max , min , N);
if(N == 0 || N == 6174) break;
}
return 0;
}
1086:Tree Traversals Again (25 分)(AC)
注意要点:
1.模板题,就是一个模拟一个栈的输入和输出。
#include<iostream>
#include<stack>
#include<cstring>
using namespace std;
const int MAX = 50;
stack<int> s;
int N;
int pre[MAX] , in[MAX] , pos[MAX];
struct node{
int data;
node* lchild;
node* rchild;
};
node* creat(int preL , int preR , int inL , int inR){
//范围//
if(preL > preR)
return NULL;
//创建根节点//
node* root = new node;
root->data = pre[preL];
//在中序遍历中找到根节点//
int k;
for(k = inL ; k <= inR ; k ++) {//千万注意这个地方如果前面定义了,则后面不能定义。//
if(pre[preL] == in[k]){
break;
}
}
//切分寻找;注意技巧:左右的范围其实是对应可以接起来的。//
int numleft = k - inL ;
root->lchild = creat(preL + 1 , preL + numleft , inL , k - 1);
root->rchild = creat(preL + numleft + 1 , preR , k + 1 , inR);
return root;
}
int num = 0 ;
void postorder(node* root) {
if(root == NULL)
return ;
postorder(root->lchild);
postorder(root->rchild);
printf("%d" , root->data);
num ++;
if(num < N)
printf(" ");
}
int main() {
int a , preindex = 0 , inindex = 0;
char opera[10];
//输入操作//
scanf("%d" , &N);
for(int i = 0 ; i < 2 * N ; i ++) {
scanf("%s" , opera);
if(strcmp(opera , "Push") == 0) {
scanf("%d" , &a);
pre[preindex ++] = a;
s.push(a);
}
else {
in[inindex ++] = s.top();
s.pop();
}
}
//建树, 这个地方注意是有几个根的数值就补几个。//
node* root = creat(0 , N - 1, 0 , N - 1);
//后序遍历//
postorder(root);
return 0;
}
1101:Quick Sort(25 分)(AC)
注意要点:
1.思路很清晰,但是这个地方可以利用这个小技巧,因为你每次前面的数据就是这个这个最小值了,所以完全没有必要每次都去遍历前面的数据,直接可以与上一个数据进行比较就行。
2.本题目和QS完全没有任何关系,倒像是在给你介绍QS的原理。
2.这个地方注意有个坑,最后需要输出一个回车。我其实很费解这个东西。以后建议所有的题目之后都去写一个回车以防万一。
#include<iostream>
#include<algorithm>
using namespace std;
const int INF = 1000000000;
int main() {
int N , sum = 0;
int a[100005] = {0};
int leftmax[100005] = {0};
int rightmin[100005] = {0};
//input//
scanf("%d" , &N);
leftmax[0] = 0;
rightmin[N - 1] = INF;
for(int i = 0 ; i < N ; i ++) {
scanf("%d" , &a[i]);
}
//leftmax:可修正,其实完全不必每次都把数据遍历一次//
for(int i = 1 ; i < N ; i ++) {
leftmax[i] = max(leftmax[i - 1] , a[i - 1]);
}
//rightmin,这个地方你想,如果要是N - 1 的话,N - 1 + 1 不就翻出数组外头去了。。//
for(int i = N - 2; i >= 0 ; i --) {
rightmin[i] = min(rightmin[i + 1] , a[i + 1]);
}
//statistic//
for(int i = 0 ; i < N ; i ++) {
if(a[i] > leftmax[i] && a[i] < rightmin[i]) {
sum ++;
}
}
//output//
printf("%d\n" , sum);
for(int i = 0 ; i < N ; i ++) {
if(a[i] > leftmax[i] && a[i] < rightmin[i]) {
printf("%d" , a[i]);
sum--;
if(sum != 0) printf(" ");
}
}
printf("\n");//无厘头的要求。//
return 0;
}
1107:Social Clusters(30 分)(AC)
注意要点:
1/并查集。最难的不是并查集,而是主函数。
#include<iostream>
#include<algorithm>
using namespace std;
int father[1005] = {0} ;
int isroot[1005] = {0} ;
int hobby[1005] = {0};
void init(int N) {
for(int i = 1 ; i <= N ; i ++) {
father[i] = i;
isroot[i] = false;
}
}
bool cmp(int a , int b) {
return a > b ;
}
int findfather(int x) {
int a = x;
while(x != father[x]) {
x = father[x];
}
while(a != father[a]){
int z = a;
a = father[a];
father[z] = x ;
}
return x;
}
void Union(int a , int b) {
int A = findfather(a);
int B = findfather(b);
if(A != B) {
father[A] = B ;
}
}
int main() {
int N , k , d , sum = 0;
scanf("%d" , &N);
init(N);
for(int i = 1 ; i <= N ; i ++){
scanf("%d: " , &k);
for(int j = 0 ; j < k ; j ++) {
scanf("%d" , &d);
if(hobby[d] == 0) {
hobby[d] = i;
}
Union(i , findfather(hobby[d]));
}
}
for(int i = 1 ; i <= N ; i ++) {
isroot[findfather(i)] ++;
}
for(int i = 1 ; i <= N ; i ++) {
if(isroot[i] != 0) {
sum ++;
}
}
sort(isroot + 1 , isroot + N + 1 , cmp);
printf("%d\n" , sum);
for(int i = 1 ; i <= sum ; i++) {
if(i == sum)
printf("%d" , isroot[i]);
else
printf("%d " , isroot[i]);
}
return 0;
}
1155. Heap Paths
解题思路:参考柳神。有的时候发现并不是不会做题,而是题目真的看不懂。。
1.利用dfs保存每条路径。(在dfs中打印数据)
2.判断大根堆和小根堆。(在大根堆中父亲节点的数据大于儿子节点的数据)
#include<iostream>
#include<vector>
using namespace std;
int n , a[1005];
vector<int> v;
void dfs(int x){
if(2 * x > n && 2 * x + 1 > n){//×ó¸ù½ÚµãµÄÊýÖµ´óÓÚÕû¸öÊý¾Ý && ÓÒ¸ú½ÚµãµÄÊý¾Ý´óÓÚÕû¸öÊý¾Ý//
if(x <= n){//Õâ¸ö¸ùµÄ½ÚµãûÓгöÁ˽磬µ«ÊÇÕâ¸ö¸ùµÄ½Úµã³öÁ˽磬Ôò˵Ã÷Õâ¸öµØ·½µ½ÁËÄ©¶ËÁË//
for(int i = 0 ; i < v.size() ; i ++){//Õâ¸öµØ·½Ï൱ÓÚÊǶÔÓÚÕû¸ö·¾¶µÄÒ»¸ö±éÀú¡£
printf("%d%s" , v[i] , i != v.size() - 1 ? " " : "\n");
}
}
}
else{
v.push_back(a[2 * x + 1]);//ÏȽ«ÓÒ½Úµã·ÅÈ룬±éÀúÓÒ½ÚµãϵÄÊ÷//
dfs(2 * x + 1);
v.pop_back();
v.push_back(a[2 * x]);//ÔÙ½«×ó½Úµã·ÅÈ룬±éÀú×ó½ÚµãϵÄÊ÷//
dfs(2 * x);
v.pop_back();
}
}
int main(){
bool ismin = false , ismax = false;
scanf("%d" , &n);
for(int i = 1 ; i <= n ; i ++){
scanf("%d" , &a[i]);
}
v.push_back(a[1]);
dfs(1);
for(int i = 2 ; i <= n ; i ++){//Õâ¸öµØ·½´ÓµÚ¶þ¸ö½Úµã¿ªÊ¼,Èç¹û´ÓµÚÒ»¸ö½ÚµãÒ²¿ÉÒÔ//
if(a[i / 2] < a[i]) ismin = true;//Èç¹û×Ó½ÚµãµÄÊýÖµ±È¸ù½ÚµãµÄÊýֵҪСµÄ»°£¬ÊÇ´ó¸ù¶Ñ//
if(a[i / 2] > a[i]) ismax = true;//Èç¹û×Ó½ÚµãµÄÊýÖµ±È¸ù½ÚµãµÄÊýÖµÒª´óµÄ»°£¬ÔòÊÇС¸ù¶Ñ//
}
if(ismax == true && ismin == true){
printf("Not Heap");
}
else if(ismax == true){
printf("Max Heap");
}
else if(ismin == true){
printf("Min Heap");
}
return 0;
}