2022 Winter Individual Contest - A(补题+反思)

https://vjudge.csgrandeur.cn/contest/475668#overview

D - Brackets 大佬题解

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e3+10;

char str[N];
int n,arr[N];
bool dp[N][N][3];
bool vis[N][N][3];

//当前为第i位,从1到i括号和,当前状态;
//搜索顺序
//000000
//000001
//000002
//000011
//000012
//000022
//000111
//000112
//······
bool f(int i,int sum,int sta){
	if(sum<0) return 0;
	if(sta>2) return 0;
	if(i==n+1){
		if(sum==0) return 1;
		else return 0;
	}
	if(vis[i][sum][sta]) return dp[i][sum][sta];
	
	bool t=0;
	if(sta==0) t|=f(i+1,sum+arr[i],sta);
	else if(sta==1) t|=f(i+1,sum-arr[i],sta);
	else t|=f(i+1,sum+arr[i],sta);
	
	t|=f(i,sum,sta+1);
	
	vis[i][sum][sta]=1;
	return dp[i][sum][sta]=t;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);  cout.tie(0);

    cin>>str+1;
    n=strlen(str+1);
     
    for(int i=1;i<=n;i++){
    	if(str[i]=='(') arr[i]=1;
    	else if(str[i]==')') arr[i]=-1;
	}
	
	if(f(1,0,0)) cout<<"possible";
	else cout<<"impossible";
    return 0;
}

H - Nine Packs
没想出来用01背包,脑子不太灵光。
看题解后第一个想法就是这也太神奇了吧,还能这样用。

整理完这道题后感觉01背包问题就是:
一组数据,存在某种约束条件的情况下,有目的性的取与不取的问题.

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,INF=0x3f3f3f3f;
int n,suma,arr[N],dpa[N];
int m,sumb,brr[N],dpb[N];
//dpa[i]表示,i这个数最少能用几个arr[i]的和表示,apa[0]=0; 
int main(){
	ios::sync_with_stdio(false);
    cin.tie(0);  cout.tie(0);
    
    memset(dpa,0x3f,sizeof dpa);
    memset(dpb,0x3f,sizeof dpb);
    
	cin>>n;dpa[0]=0;
    for(int i=1;i<=n;i++) cin>>arr[i],suma+=arr[i];
	cin>>m;dpb[0]=0;
	for(int i=1;i<=m;i++) cin>>brr[i],sumb+=brr[i];
	
	for(int i=1;i<=n;i++){
		for(int j=suma;j>=arr[i];j--){
			if(dpa[j-arr[i]]!=INF){
				dpa[j]=min(dpa[j-arr[i]]+1,dpa[j]);
			}
		}
	}
	for(int i=1;i<=m;i++){
		for(int j=sumb;j>=brr[i];j--){
			if(dpb[j-brr[i]]!=INF){
				dpb[j]=min(dpb[j-brr[i]]+1,dpb[j]);
			}
		}
	}
	suma=min(suma,sumb);
	int minn=INF;
	for(int i=1;i<=suma;i++){
		if(dpa[i]==INF||dpb[i]==INF) continue;
		minn=min(dpa[i]+dpb[i],minn);
	}
	if(minn==INF) cout<<"impossible";
	else cout<<minn;
}

A - A New Alphabet
简单题更要小心陷阱啊

cout<<"\\ \\n \\t";//转义字符输出

C - Big Truck
比赛时直接改的模板,现在自己默写一遍

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e3+10;

int n,arr[N],gp[N][N],dis[N],vis[N],cnt[N]; 
int m;

void dijkstra(){
	memset(dis,0x3f,sizeof dis);
	
	dis[1]=0;cnt[1]=arr[1];
	for(int j=1;j<=n;j++){
		int k=0;
		for(int i=1;i<=n;i++){
			if(!vis[i]&&(k==0||dis[i]<dis[k])){
				k=i;
			}
		}
		vis[k]=1;
		for(int i=1;i<=n;i++){
			if(dis[i]>dis[k]+gp[k][i]){
				dis[i]=dis[k]+gp[k][i];
				cnt[i]=cnt[k]+arr[i];
			}
			else if(dis[i]==dis[k]+gp[k][i]){
				cnt[i]=max(cnt[i],cnt[k]+arr[i]);
			}
		}
	}
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);  cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++) cin>>arr[i];
    cin>>m;
    int a,b,c;
    memset(gp,0x3f,sizeof gp);
    for(int i=1;i<=m;i++){
    	cin>>a>>b>>c;
    	gp[a][b]=gp[b][a]=c;
	}
	

	dijkstra();
	if(dis[n]==0x3f3f3f3f) cout<<"impossible";
	else cout<<dis[n]<<" "<<cnt[n];
    return 0;
}

G - Inverse Factorial

不断取模相等就过了,可能数据太水了吧
赛后看题解正解应该就是通过两边取log10把左边的大数转化为它的位数,右边的乘转为加,极大的减小了数据范围

#include<bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(false);
    cin.tie(0);  cout.tie(0);
    
    string str;cin>>str;
    int n=str.length();
    if(n<=8){//数据小的时候就正常暴力算
    	int sum=0;
    	for(int i=0;i<=n-1;i++){
    		sum=sum*10+str[i]-'0';
		}
		int ans=1;
		for(int i=1;;i++){
			ans=ans*i;
			if(sum==ans) cout<<i,return 0;
		}
	}
    else{//n是位数,而log大约是n-1;
    	n=n-1;
    	double ans=0;
		for(int i=1;;i++){
	    	ans+=log10(i);
	    	if(ans>=n) cout<<i,return 0;
		}
	}
    
    return 0;
}

K - Robotopia
题干说:
with at least one of each type in each group
这两组每组至少有一个机器人
但我理解成了这两组至少有一个机器人,就导致wa了好多次

还有一个坑就是当两组方程等比例的时候,即
a1x+a2y==at;
k*(a1x+a2y)==k*at;
的时候,方程是个二元一次方程,不好确定解的个数
比如x+y=2的解只有一种,x+y=100有好几个
数据不大暴力循环判断就行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值