计算A+B

链接:https://ac.nowcoder.com/acm/contest/11455/J
来源:牛客网

题目描述
在一行中给出一个字符串,请判断是否满足A + B格式,如果满足,输出计算结果,否则输出"skipped"。
此处A,B均为大于等于0的整数,不保证数据没有前导零。
输入描述:
第一行输入一个n, 1 \le n \le 1000n,1≤n≤1000,代表测试数据的组数。
接下来n行,每行输入一个长度不超过10000的字符串。
输出描述:
对于每组输入,输出结果
示例1
输入
复制
4
2+2
1+2
+12
0+0
输出
复制
4
3
skipped
0

注意加法的特征,必须是一个加号,并且加号的两边都有数,最后用到高精度加起来就行

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
//#include <algorithm>

//#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
//#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 5010;
const int M = 35;
const int mod = 1e9 + 7;
const int PP = 131;
const double eps = 1e-10;
		
string str;

string calc(int l, int r){
	if (l > r)   return "*";
	
	string str1 = "";
	bool flag = false;
	for (int i = l; i <= r; i ++){
		int x = (str[i] - '0');
	//	cout << x << " " <<str[i] << endl;
		if (x || flag){
			str1 += str[i];
			flag = true;
		}
	}
	
	if (!flag)   str1 = "0";
	return str1;
}

vector<int> add(vector<int> &A, vector<int> &B)
{
    if (A.size() < B.size()) return add(B, A);

    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }

    if (t) C.push_back(t);
    return C;
}


signed main(){
//	ios;
	int n;
cin >> n;
	while(n --){
		cin >> str;
		bool flag3 = false;
		
		int cnt = 0;
		for (int i = 0; i < str.size(); i ++){
		    if (str[i] == '+')   cnt ++;
		    else if (str[i] >= '0' && str[i] <= '9')   continue;
		    else   flag3 = true;
		}
		if (flag3 || cnt >= 2 || cnt == 0) {
		       cout << "skipped" << endl;
		       continue;
		}
	//	cout << str << endl;
		for (int j = 0; j < str.size(); j ++){
		   // cout << str[j] << endl;
			if (str[j] == '+'){
			//	flag3 = true;
				//cout << j << endl;
				string a = calc(0, j - 1);
				string b = calc(j + 1, str.size() - 1);
				if (a == "*" || b == "*")   cout << "skipped" << endl;
				else{
				           // cout << a << endl;
				            //cout << b << endl;
					      vector<int> A, B;
					      for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
                          for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

                         auto C = add(A, B);

                      for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
                   cout << endl;
				}
                break;
			}
		}
		//if (!flag3)    cout << "skipped/" << endl;
	}
	return 0;
}

仓库选址

链接:https://ac.nowcoder.com/acm/contest/11455/G
来源:牛客网

题目描述
牛能在某小城有了固定的需求,为了节省送货的费用,他决定在小城里建一个仓库,但是他不知道选在哪里,可以使得花费最小。
给出一个m \times nm×n的矩阵,代表下一年小城里各个位置对货物的需求次数。我们定义花费为货车载货运输的距离,货车只能沿着水平或竖直方向行驶。

输入描述:
首先在一行中输入T , T \le 10T,T≤10,代表测试数据的组数。
每组输入在第一行给出两个正整数n, m, 1 \le n,m \le 100n,m,1≤n,m≤100,分别代表矩阵的宽和高。
接下来m行,每行n个不超过1000的数字,代表矩阵里的元素。
输出描述:
每组输入在一行中输出答案。
示例1
输入
复制
3
2 2
1 1
1 0
4 4
0 8 2 0
1 4 5 0
0 1 0 1
3 9 2 0
6 7
0 0 0 0 0 0
0 1 0 3 0 1
2 9 1 2 1 2
8 7 1 3 4 3
1 0 2 2 7 7
0 1 0 0 1 0
0 0 0 0 0 0
输出
复制
2
55
162
备注:
送货时只能单次运输,若该位置需要3次,货车必须跑3次。
即使该位置需要被送货,我们仍然可以选择该位置作为仓库。

直接暴力枚举仓库的位置即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
//#include <vector>
//#include <algorithm>

//#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int long long
//#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 110;
const int M = 35;
const int mod = 1e9 + 7;
const int PP = 131;
const double eps = 1e-10;

int a[N][N];

signed main(){
	int T;
	gt(T);
	
	while(T --){
		int n, m;
		gt(m), gt(n);
		
		for (int i = 1; i <= n; i ++){
			for (int j = 1; j <= m; j ++){
				scanf("%lld", &a[i][j]);
			}
		}
		//cout << "------" << endl;
		
		int ans = 0x7f7f7f7f;
		for (int i = 1; i <= n; i ++){
			for (int j = 1; j <= m; j ++){
				int sum = 0;
				for (int k = 1; k <= n; k ++){
					for (int p = 1; p <= m; p ++){
						sum += (a[k][p] * (abs(k - i) + abs(p - j)));
					}
				}
				
			//	cout << sum << "----" << endl;
				ans = min(ans, sum);
			}
		}
			cout << ans << endl;
	}

	
	return 0;
}

收集纸片

链接:https://ac.nowcoder.com/acm/contest/11455/D
来源:牛客网

题目描述
我们把房间按照笛卡尔坐标系进行建模之后,每个点就有了一个坐标。
假设现在房子里有些纸片需要被收集,收集完纸片你还要回归到原来的位置,你需要制定一个策略来使得自己行走的距离最短。
你只能沿着 x 轴或 y 轴方向移动,从位置 (i,j) 移动到相邻位置 (i+1,j),(i-1,j),(i,j+1) 或 (i,j-1) 距离增加 1。

输入描述:
在第一行中给出一个T, 1 \le T \le 10T,1≤T≤10, 代表测试数据的组数。
对于每组输入,在第一行中给出房间大小,第二行给出你的初始位置。
接下来给出一个正整数 n,1 \le n \le 10n,1≤n≤10 代表纸片的个数。
接下来 n 行,每行一个坐标代表纸片的位置。
保证房间小于 20 \times 2020×20,纸片一定位于房间内。
输出描述:
对于每组输入,在一行中输出答案。
格式参见样例。
示例1
输入
复制
1
10 10
1 1
4
2 3
5 5
9 4
6 5
输出
复制
The shortest path has length 24

纸片的数目很少,所以只需要爆搜出所有纸片的顺序,然后每种顺序求一个最小值即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
//#include <vector>
//#include <algorithm>

//#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int long long
//#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 110;
const int M = 35;
const int mod = 1e9 + 7;
const int PP = 131;
const double eps = 1e-10;

struct Node{
	int a, b;
}node[M];
int cnt;
bool st[N];
int state[N];
int ans;
int x, y;

int calc(){
	int nowx = x;
	int nowy = y;
	
	int sum = 0;
	for (int i = 0; i < cnt; i ++){
		sum = sum + abs(node[state[i]].a - nowx) + abs(node[state[i]].b- nowy);
		nowx = node[state[i]].a;
		nowy = node[state[i]].b;
	}	
	
	sum = sum + abs(nowx - x) + abs(nowy - y);
	return sum;
}

void dfs(int u){
	if (u == cnt){
		int sum = calc();
		ans = min(sum, ans);
		return;
	}
	
	    for (int i = 1; i <= cnt; i ++ )
        if (!st[i])
        {
            state[u] = i;
            st[i] = true;
            dfs(u + 1);

            state[u] = 0;
            st[i] = false;
        }
}

signed main(){
	int T;
	gt(T);
	
	while(T --){
		ans = 0x7f7f7f7f;
		int n, m;
		gt(n), gt(m);
		

		cin >> x >> y;
		
		cin >> cnt;
		for (int i = 1; i <= cnt; i ++){
			cin >> node[i].a >> node[i].b;
		}
		
		dfs(0);
		
		 printf("The shortest path has length %d\n", ans);
	}
	
	return 0;
}
#include<iostream>
#include<cmath>
#include<cstring>

using namespace std;
const int N=12;

int a[N],b[N];
int k;
int ans,fi,si,tmp;
bool st[N];

void dfs(int x,int y,int u)
{
    if(u>k)
    {
        tmp+=abs(x-fi)+abs(y-si);
        //cout<< abs(x-fi)+abs(y-si) <<endl;
        //cout<< fi << " " << si <<endl;
        //cout<< x <<" "<<y<<"----"<<endl;
        ans=min(ans,tmp);
        tmp-=abs(x-fi)+abs(y-si);
        //cout<< tmp <<endl;
        return;
    }
    for(int i=1;i<=k;i++)
    {
        if(!st[i])
        {
            st[i]=true;
            tmp+=abs(x-a[i])+abs(y-b[i]);
            //cout<< tmp <<endl;
            dfs(a[i],b[i],u+1);
            st[i]=false;
            tmp-=abs(x-a[i])+abs(y-b[i]);
            //cout<< tmp <<endl;
        }
    }
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        ans=0x3f3f3f3f;
        tmp=0;
        int n,m; 
        cin>>n>>m;
        cin>>fi>>si;
        cin>>k;
        a[0]=fi,b[0]=si;
        memset(st,0,sizeof st);
        for(int i=1;i<=k;i++)
            scanf("%d%d",&a[i],&b[i]);
        dfs(fi,si,1);
        printf("The shortest path has length %d\n",ans);
    }
    return 0;
}

树上子链
链接:https://ac.nowcoder.com/acm/contest/11455/B
来源:牛客网

题目描述
给定一棵树 T ,树 T 上每个点都有一个权值。
定义一颗树的子链的大小为:这个子链上所有结点的权值和 。
请在树 T 中找出一条最大的子链并输出。
输入描述:
第一行输入一个 n,1 \le n \le 10^5n,1≤n≤10
5

接下来一行包含n个数,对于每个数 a_i, -10^5 \le a_i \le 10^5a
i

,−10
5
≤a
i

≤10
5
,表示 i 结点的权值。
接下来有n-1行,每一行包含两个数u,v( 1 \le u,v \le n1≤u,v≤n , u != v),表示u与v之间有一条边。
输出描述:
仅包含一个数,表示我们所需要的答案。
示例1
输入
复制
5
2 -1 -1 -2 3
1 2
2 3
2 4
2 5
输出
复制
4
说明
样例中最大子链为1 -> 2 -> 5
备注:
一个结点,也可以称作一条链

最长的子链即为求树的最长路径,求树的最长路径有两种方法,一种是按照链的中点,把两根链绑到一块,一种是先走到最远点,然后从这个和最远的点再走到最远的点
这里把两种方法的代码都给出

#include <iostream>
#include <cstring>
#include <cstdio>
//#include <vector>
//#include <algorithm>

//#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 2e5 + 10;
const int M = 35;
const int mod = 1e9 + 7;
const int PP = 131;
const double eps = 1e-10;

int f[N];
int w[N];
int h[N], ne[N], e[N], idx;
bool st[N];

void add(int a, int b){
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int ans;
void dfs(int u, int father){
	 f[u] = w[u];
//	cout << u << endl;
	//if (st[u])   return;
	//st[u] = true;
	for (int i = h[u]; ~i; i = ne[i]){
		int j = e[i];
		if (j == father)   continue;
		dfs(j, u);
	//	if (f[j] > 0)   f[u] += f[j];
	  //  cout << j << "  " << f[j] << " " << u << " " << f[u] << endl;
		ans = max(ans, f[j] + f[u]);
		f[u] = max(f[u], f[j] + w[u]);
	}
//	cout << u << "----------" << f[u] << endl;
	ans = max(ans, f[u]);
	return;
}

signed main(){
	int n;
	gt(n);
	memset(h, -1, sizeof h);
	for (int i = 1; i <= n; i ++)    scanf("%lld", &w[i]);
	
//	for (int i = 1; i <= n; i ++)   cout << w[i] << endl;
	
	for (int i = 1; i < n; i ++){
		int a, b;
		gt(a), gt(b);
		add(a, b), add(b, a);
	}
	
	 ans = -0x7f7f7f7f;
	dfs(1, -1);
			
	cout << ans << endl;
	
	return 0;
}
#include<iostream>
#include<cstring>

using namespace std;
typedef long long LL;
const int N=1e5+10,M=2*N;

int h[N],e[M],ne[M],w[N],idx;
LL dist1[N],dist2[N];

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs1(int u,int fa)
{
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j==fa) continue;
        dist1[j]=dist1[u]+w[j];
        dfs1(j,u);
    }
}

void dfs2(int u,int fa)
{
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j==fa) continue;
        dist2[j]=dist2[u]+w[j];
        dfs2(j,u);
    }
}

int main()
{
    int n;
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    for(int i=1;i<n;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
    dist1[1]=w[1];
    dfs1(1,-1);
    int u=0;
    LL dis=-0x3f3f3f3f3f3f3f3f;
    for(int i=1;i<=n;i++)  if(dist1[i]>dis) dis=dist1[i],u=i;
    dist2[u]=w[u];
    dfs2(u,-1);
    int p=0;
    dis=-0x3f3f3f3f3f3f3f3f;
    for(int i=1;i<=n;i++)  if(dist2[i]>dis) dis=dist2[i],p=i;
    cout<< dis <<endl;
    return 0;
}

操作序列
链接:https://ac.nowcoder.com/acm/contest/11455/A
来源:牛客网

题目描述
给出一个长度无限的数列,初始全部为零,有三种操作:

增加操作:给下标为 tt 的数加 cc 。特别注意,如果在下标 [t-30,t+30][t−30,t+30] 内有不为零的数,增加操作无效。
削减操作:让数列中下标最小的不为零数变为零。
查询操作:查询数列中下标为 tt 的数字是多少。
输入描述:
第一行包含一个整数 N,1 \le N \le 10^6N,1≤N≤10
6
,表示操作总数。
随后 N 行,每行由两个数字或一个数字组成。
若一行中有两个数字,分别代表增加操作的 t,c 。
若一行中只有数字-1,执行削减操作。
若一行中只有一个不为 -1的数字,则代表查询操作的数字 t。
保证t,c均为非负整数且在整形范围内。
输出描述:
削减操作时,先输出该数字,再变为零
若序列元素全为零,则削减操作无效,此时输出 “skipped”
查询时,输出该位置上的数
示例1
输入
复制
7
140 1
120 2
100 3
120
100
-1
100
输出
复制
0
3
3
0
示例2
输入
复制
4
140 3
-1
140 1
-1
输出
复制
3
1
示例3
输入
复制
3
-1
-1
-1
输出
复制
skipped
skipped
skipped

操作序列

判断下一个是否有数字可以getchar()看是否可以读取到字符
map的一些常用操作
mp.count(i) i那个位置上是否有数
mp.empty()这个map是否是空的
mp.begin() -> second第一个有的数字
mp.erase(mp.begin());删除第一个数字

#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
//#include <vector>
//#include <algorithm>

//#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int long long
//#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

map<int, int> mp;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e5 + 10;
const int M = 35;
const int mod = 1e9 + 7;
const int PP = 131;
const double eps = 1e-10;

signed main(){
	int T;
	gt(T);

	while(T --){
		int x, y;
		char c;
		cin >> x;
		c = getchar();
		if (c == ' '){
			cin >> y;
			bool flag = false;
			for (int i = x - 30; i <= x + 30; i ++)
               if (mp.count(i))    flag = true;
            if (!flag)    mp[x] = y;
            continue;
		}
		
		if (x == -1){
			 if (mp.empty()) puts("skipped");
            else {
                printf("%d\n", mp.begin() -> second);
                mp.erase(mp.begin());
            }
		}
		else{
			if (mp.count(x))   cout << mp[x] << endl;
			else   cout << "0" << endl;
		}
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值