https://vjudge.csgrandeur.cn/contest/475668#overview
#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有好几个
数据不大暴力循环判断就行