比赛链接
C.题意题,读懂之后枚举即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,s,cnt;
int main() {
for(scanf("%d",&t);t;t--){
printf("Case #%d: ",++cnt);
scanf("%d%d",&n,&s);
int ans=-2e9;
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
if(y<=s)ans=max(ans,x);
else ans=max(ans,x-(y-s));
}
cout<<ans<<'\n';
}
return 0;
}
E.dp记录路径 ,注意:不能重复选和先出现的先选原则,所有倒着来dp即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,a[N],vis[1111][1111],pre[1111][1111];
int main() {
ios::sync_with_stdio(false);
while(1){
cin>>t;
if(!t)break;
memset(vis,0,sizeof vis);
memset(pre,0,sizeof pre);
cin>>n;vis[n+1][0]=1;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=n;i>=1;i--){
for(int j=a[i];j<=t;j++){
if(vis[i+1][j-a[i]]){
vis[i][j]=1;
pre[i][j]=i;
}
}
for(int j=0;j<=t;j++){
if(!vis[i][j]){
vis[i][j]=vis[i+1][j];
pre[i][j]=pre[i+1][j];
}
}
}
for(int i=t;i>=0;i--){
if(vis[1][i]){
int la=i,l=1;
while(la){
cout<<a[pre[l][la]]<<' ';
int z=pre[l][la];
la-=a[pre[l][la]];
l=z+1;
}
cout<<i<<'\n';
break;
}
}
}
return 0;
}
F.状态压缩dp,显然第一个排的每个人只能选
[
i
−
e
,
i
+
e
]
[i-e,i+e]
[i−e,i+e]范围内的人,那么
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示第i个人
[
i
−
e
,
i
+
e
]
[i-e,i+e]
[i−e,i+e]范围的人的状态(选了是1 不选为0)的选择方案数。
然后枚举所有人,枚举前一个人的所有状态,进行判断。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e3 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int dp[N][1<<10];
bool ban[N][N];
int n,e,k;
const int mod=1e9+7;
void add(int &x,int y){
x+=y;
if(x>=mod)x-=mod;
}
int main() {
ios::sync_with_stdio(false);
cin>>n>>e>>k;
for(int i=1;i<=k;i++){
int s,t;
cin>>s>>t;
ban[s][t]=1;
}
dp[0][0]=1;
int c=2*e+1;
for(int i=1;i<=n;i++){
int l=max(1,i-e);
int r=min(n,i+e);
int dx=max(1,i-1-e);
int dy=min(n,i-1+e);
for(int j=0;j<1<<c;j++){
for(int k=l;k<=dy;k++){
if(!((1<<(k-(i-1-e)))&j)){
if(!ban[i][k]){
add(dp[i][(j|(1<<k-(i-1-e)))>>1],dp[i-1][j]);
}
}
}
if(!ban[i][r]){
add(dp[i][j>>1|(1<<e+e)],dp[i-1][j]);
}
}
}
cout<<dp[n][(1<<e+1)-1]<<endl;
return 0;
}
J.拓扑排序模板题。
ps:由于数据很小,所以其他的一些模拟做法都是可以的。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
vector<int>v[N];
int d[N],ans[10];
char a[5];
int main() {
ios::sync_with_stdio(false);
for(int i=1;i<=5;i++){
cin>>a+1;
if(a[2]=='>')v[a[3]-'A'].pb(a[1]-'A'),d[a[1]-'A']++;
else{
v[a[1]-'A'].pb(a[3]-'A');
d[a[3]-'A']++;
}
}
queue<int>q;
for(int i=0;i<5;i++)if(!d[i])q.push(i);
int cnt=0;
while(!q.empty()){
int x=q.front();
q.pop();
ans[++cnt]=x;
for(auto k:v[x]){
if(--d[k]==0)q.push(k);
}
}
if(cnt!=5){
return cout<<"impossible\n",0;
}
for(int i=1;i<=5;i++){
cout<<(char)(ans[i]+'A');
}
return 0;
}