牛客寒假算法基础集训营6 题解报告

比赛地址 : https://ac.nowcoder.com/acm/contest/332#question

A: 考虑一下极限位置就行

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;

int main()
{
	std::ios::sync_with_stdio(false);
	ll n,m, seven,nine;
	while(cin >> n >> m)
	{
		seven = 7*m;
		nine = 9 * m;
		if(n >9*m || n < 6*m || n < 0)
		{
			cout << "jgzjgzjgz" << endl;
		}	
		else if(seven <= n)
			cout << "0" << endl;
		else if(seven > n)
			cout << (seven-n) << endl;
	}

	return 0;
}  

B :暴力

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;

int main()
{
	std::ios::sync_with_stdio(false);
	ll n, m, d, x, t, ans;
	while(cin >> n >> m >> d >> x)
	{
		ans = n;
		if(ans >= m)
		{
			cout << "1"<< endl;continue;
			
		}
		for(t = 2; t <= x; t++)
		{
			n += d;
			ans += n;
			if(ans >= m)
			{
				cout << t<< endl;break;
				
			}
				
			 
			
		}
	}

	return 0;
} 

C:贪心,从喜爱值最大的开始贪就行

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
struct node
{
	int tol, value;
}mp[100005];

bool cmp(node a, node b)
{
	return a.value > b.value;
}

int main()
{
	std::ios::sync_with_stdio(false);
	int n, m, i;
	ll ans;
	while(cin >> n >> m)
	{
		ans = 0;
		for(i = 0; i < m; i++)
		{
			cin >> mp[i].tol;
		}
		for(i = 0; i < m; i++)
		{
			cin >> mp[i].value;
		}
		sort(mp,mp+m,cmp);
		for(i = 0; i < m && n; i++)
		{
			if(n >= mp[i].tol)
			{
				ans += mp[i].tol*mp[i].value;
				n -= mp[i].tol;
			}
			else 
			{
				ans += n * mp[i].value;
				n = 0;
				break;
			}
		}
		cout << ans << endl;
	}

	return 0;
} 

 

D:考虑一下 1001 这个坑  然后第一个偶数就全部吃掉,如果奇数就留一口,接下来后面的就先考虑一下前面一个是否留了一口,优先吧前面留的那口吃掉

 

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
ll mp[100005];
int main()
{
	std::ios::sync_with_stdio(false);
	int n, i;
	ll ans, sum;
	while(cin >> n)
	{
		sum = ans = 0;
		for(i = 0; i < n; i++)
		{
			cin >> mp[i];
		}
		for(i = 0; i < n; i++)
		{
			if(mp[i])
			{
				if(i==0)
				{
					ans+= mp[i]/2;
					mp[i] -= 2*ans;
				}
				else if(mp[i]%2==0)
				{
					if(mp[i-1]==0)
					{
						ans += mp[i]/2;
						mp[i]=0;
					}
					else 
					{
						ans += mp[i]/2;
						mp[i]=1;
					}
				}
				else if(mp[i]%2!=0)
				{
					ans += mp[i]/2;
					mp[i] = 1;
					if(mp[i-1]==1)
					{
						mp[i] = 0;
						mp[i-1] = 0;
						ans++;
					}
				}
			}
		}
//		cout << sum / 2 << endl;
		cout << ans << endl;
	}

	return 0;
} 

E:用数组ans[i][j]记住(0,0)到(i,j)有多少城市会被淹,维护一下数组就行

和这道题方法一样: https://blog.csdn.net/lanyanzhiji123asd/article/details/86674537

n*m< 10^6  这个就用动态数组分配一下。

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
//vectormp[1000005];
//vectorvis[1000005];
int *ans[1000005];
int main()
{
	int x,y,a,b,q;

	std::ios::sync_with_stdio(false);
	int n,m,d,i,j,h, cnt;
	while(cin >> n >> m >> d)
	{
		
		for(i = 1; i <= n; i++)
			ans[i] = new int [m+1];
		for(i = 1; i <= n; i++)
		{
			for(j = 1; j <= m; j++)
			{
				ans[i][j] = 0;
			}
		}
		
			
		for(i = 1; i <= n; i++)
		{
			for(j = 1; j <= m; j++)
			{
				cin >> h;
				ans[i][j] = h>=d;
					
			}
		}
		for(i = 1;i <= n; i++)
		{
			for(j = 1; j <= m; j++)
			{
				
				if(i-1>0) //cout << "qqq" << endl;
					ans[i][j]=ans[i][j]+ans[i-1][j];
				if(j-1>0)
					ans[i][j]=ans[i][j]+ans[i][j-1];
				if(i-1>0&&j-1>0)
					ans[i][j]=ans[i][j]-ans[i-1][j-1];
				
			}
		}
		cin >> q;
		while(q--)
		{
			cin >> a >> b>> x >> y;
			cnt = ans[x][y];
			if(a-1>0) cnt -= ans[a-1][y];
			if(b-1>0) cnt -= ans[x][b-1];
			if(a-1&&b-1) cnt += ans[a-1][b-1];
			cout << cnt << endl;
		}
	}

	return 0;
} 

F:最后结束的时候的情况是可以确定的,三种可能  :  石头剪刀布,由这三种情况反推最开始的可能

 

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
char str[3]={'R','P','S'};
char ans[10000005];
int mp[3],mp1[3];
void dfs(int num, int l, int r)
{
	int i,j;
	if(l==r)
	{
		ans[l] = str[num];
		mp1[num]++;	
		return;
	}
	int mid = (l+r)/2;
	if(num==0)
	{
		dfs(0,l,mid);
		dfs(2,mid+1,r);
	}
	else if(num==1)
	{
		dfs(1,l,mid);
		dfs(0,mid+1,r);
	}
	else if(num==2)
	{
		dfs(1,l,mid);
		dfs(2,mid+1,r);
	}
	int flag = 0;
	for(i = l,j = mid+1;i<=mid&&j<=r;i++,j++)
	{
		if(ans[i]>ans[j])
		{
			flag = 1;
			break;
		}
	}
	if(flag)
	{
		for(i = l,j = mid+1;i<=mid&&j<=r;i++,j++)
		{
			swap(ans[i],ans[j]);
		}
	}
}

int main()
{
	std::ios::sync_with_stdio(false);
	int r,p,s;
	while(cin >> mp[0] >> mp[1]>> mp[2])
	{
		memset(mp1,0,sizeof(mp1));
		int flag = 0,i;
		for(i = 0; i <= 2; i++)
		{
			memset(mp1,0,sizeof(mp1));
			dfs(i,0,(mp[0]+mp[1]+mp[2]-1));
//			cout << mp1[0] << "  " << mp1[1] << "  " << mp1[2] << endl;
			ans[mp[0]+mp[1]+mp[2]] = '\0';
			if(mp1[0]==mp[0]&&mp1[1]==mp[1]&&mp1[2]==mp[2])
			{
				flag = 1;cout << ans << endl;
				break;
			}
				
		}
		if(!flag)
		{
			cout << "IMPOSSIBLE" << endl;
		}
		
	} 

	return 0;
} 

 

G:这道题我实在想不明白   放个博客吧,这个博客写的不错   http://keyblog.cn/article-67.html?tdsourcetag=s_pctim_aiomsg

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
ll a,b;
string ans;
ll cnt;


int main()
{
	std::ios::sync_with_stdio(false);
	int i,j;
	while(cin >> a >> b)
	{
		while(a

H:这道题就是求出每头猪从那头猪进化过来花费最少,可以是第1头猪,第二头猪,第三头猪…… 也可以是自己,所以用 i 枚举表示进化多少次,求出最小值就行  这个方法真是妙呀   我是一个小菜鸡小菜鸡o(╥﹏╥)o

#include
using namespace std;
#define ll long long int
const ll INF = 0x3f3f3f3f3f3f3f3f;//这里注意一下,不然会WA 
const int mod = 998244353;
ll b[20005],mp[20005],x;
int main()
{
	std::ios::sync_with_stdio(false);
	int n, i, j;
	ll ans;
	while(cin >> n >> x)
	{
		ans = INF;
		memset(b,INF, sizeof(b));
		for(i = 0; i < n; i++)
			cin >> mp[i];
		for(i = 0; i < n; i++)
		{
			ll sum = 0;
			for(j = 0; j < n; j++)
				b[j] = min(b[j],mp[(j-i+n)%n]);
			for(j = 0; j < n; j++)
				sum += b[j];
			ans = min(ans, sum+i*x);
		}
		cout <

 

I : 一串01组成的序列,如果00 或11配对了就直接算10,用栈维护下,这样最后一定剩下的是01交叠的串,直接算就行

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
string str;
int mp[1000005];
int main()
{
	std::ios::sync_with_stdio(false);
	int ans,cnt, i;
	while(cin >> str)
	{
		memset(mp,-1,sizeof(mp));
		ans = cnt = 0;
		mp[cnt++] = str[0]-'0';
		for(i = 1; i < str.length(); i++)
		{
			if(mp[cnt-1]!=str[i]-'0' || cnt==0)
			{
				mp[cnt++] = str[i]-'0';
			}
			else
			{
				cnt--;
				ans += 10;
			}
		}
		ans += 5*(cnt/2);
		cout << ans << endl;
	}

	return 0;
} 

J : 简单BFS  记住一下当前左边右边走了多少步判断一下就行

#include
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
int n,m,r,c,x,y;
int d[2] = {1,-1};
struct node 
{
	  int x,y,left,right;
};
int vis[1005][1005];
string str[1005];

int access(node tt)
{
	if(tt.x=0&&tt.y=0&&!vis[tt.x][tt.y]&&str[tt.x][tt.y]!='*')
		return 1;
	return 0;
}

void BFS()
{
	memset(vis, 0, sizeof(vis));
	int ans = 0, i;
	node temp;
	temp.x=r;
	temp.y=c;
	temp.left = 0;
	temp.right=0;
	queueq;
	q.push(temp);
	vis[temp.x][temp.y] = 1;
	ans++;
	while(!q.empty())
	{//cout<< "qqq" << endl;
		node v = q.front();
		q.pop();
		temp.x = v.x;
		temp.y = v.y-1;
		temp.left = v.left+1;
		temp.right = v.right;
		if(access(temp))
		{
			if(temp.left<=x)
			{
				q.push(temp);
				vis[temp.x][temp.y] = 1;
				ans++;
			}
		}
		temp.x = v.x;
		temp.y = v.y+1;
		temp.left = v.left;
		temp.right = v.right+1;
		if(access(temp))
		{
			if(temp.right<=y)
			{
				q.push(temp);
				vis[temp.x][temp.y] = 1;
				ans++;
			}
		}
		for(i = 0; i <= 1; i++)
		{
			temp.x = v.x+d[i];
			temp.y = v.y;
			temp.left = v.left;
			temp.right = v.right;
			if(access(temp))
			{
				q.push(temp);
				vis[temp.x][temp.y] = 1;
				ans++;
			}
		}
	}
	cout << ans << endl;
}

int main()
{
	std::ios::sync_with_stdio(false);

int i;
	while(cin >> n >> m)
	{
		cin >> r >> c;
		cin >> x>> y;
		r--,c--;
		for(i = 0; i < n; i++)
		{
			cin >> str[i];
		}
		BFS();
	}

	return 0;
} 

 

 

 

 

 

你可能感兴趣的:(牛客寒假算法基础集训营6 题解报告)