A 序号互换
进制转换问题。
#include<stdio.h>
int main()
{
int i,j,n,t,x,y,m,f,c=0,s;
char a[1000],b[1000];
scanf("%d",&n);
while(n--){
scanf("%s",a);
s=0;c=0;
if(a[0]>='0'&&a[0]<='9'){
for(i=0;a[i];i++)
s=s*10+a[i]-'0';
do{
b[c++]='A'+s%26-1;
}while(s/=26);
for(i=c-1;i>=0;i--) printf("%c",b[i]);
printf("\n");
}
else {
for(i=0;a[i]!='\0';i++)
s=26*s+(a[i]-'A'+1);
printf("%d\n",s);
}
}
return 0;
}
B 节能
洛谷上有原题 P1220 关路灯
洛谷上数据范围小一些,dfs+剪枝就可以可以过,但是省赛的数据范围太大了,只能用区间DP。
dp[i][j][0/1]表示ij区间的灯已全部熄灭,此时站着i/j的位置。
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e3+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans=inf,st;
int a[N],b[N],s[N];
int dp[N][N][2];
int main()
{
int i,j,k,x,y,z;
scanf("%d %d",&n,&st);
for(i=1;i<=n;i++){
scanf("%d %d",&a[i],&b[i]);
s[i]=s[i-1]+b[i];
}
memset(dp,inf,sizeof(dp));
dp[st][st][0]=dp[st][st][1]=0;
for(int l=2;l<=n;l++){
for(i=1;i+l-1<=n;i++){
j=i+l-1;
dp[i][j][0]=min(dp[i+1][j][0]+(a[i+1]-a[i])*(s[i]+s[n]-s[j]),//i,j外的灯需要加一次ij之间的时间消费
dp[i+1][j][1]+(a[j]-a[i])*(s[i]+s[n]-s[j]));
dp[i][j][1]=min(dp[i][j-1][1]+(a[j]-a[j-1])*(s[i-1]+s[n]-s[j-1]),
dp[i][j-1][0]+(a[j]-a[i])*(s[i-1]+s[n]-s[j-1]));
}
}
printf("%d",min(dp[1][n][0],dp[1][n][1]));
return 0;
}
自己写的dfs洛谷上的只有90分。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e4+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans=inf,st;
struct node{
int d,w;
}s[N];
int vis[N];
void dfs(int pos,int cnt,int dis,int sum){
if(sum>ans) return;
if(cnt==n){
if(sum<ans) ans=sum;
return;
}
int x;
for(x=pos-1;x>=1;x--){
if(vis[x]==0){
vis[x]=1;
dfs(x,cnt+1,dis+s[pos].d-s[x].d,sum+(dis+s[pos].d-s[x].d)*s[x].w);
vis[x]=0;
break;
}
}
for(x=pos+1;x<=n;x++){
if(vis[x]==0){
vis[x]=1;
dfs(x,cnt+1,dis+s[x].d-s[pos].d,sum+(dis+s[x].d-s[pos].d)*s[x].w);
vis[x]=0;
break;
}
}
}
int main()
{
int i,j,k,x,y,z;
scanf("%d %d",&n,&st);
for(i=1;i<=n;i++){
scanf("%d %d",&s[i].d,&s[i].w);
}
vis[st]=1;
dfs(st,1,0,0);
printf("%d",ans);
return 0;
}
C 表达式求值
模拟题,堆栈的应用。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
int main()
{
int i,j,n,k,t=0,sum=0,s1,x,y,b[1000];
char a[1000];
scanf("%d",&n);
while(n--){
scanf("%s",a);
stack<int>s;
for(i=strlen(a)-1;i>=0;i--){
if(a[i]>='0'&&a[i]<='9'){
int c=0;t=0;
while(a[i]>='0'&&a[i]<='9'){
b[c++]=a[i]-'0';i--;
}
for(j=c-1;j>=0;j--)
t=t*10+b[j];
s.push(t);
}
if(a[i]=='d'&&a[i-1]=='d'&&a[i-2]=='a') {
x=s.top();s.pop();
y=s.top();s.pop();
t=x+y;
s.push(t);
i-=2;
}
else if(a[i]=='x'&&a[i-1]=='a'&&a[i-2]=='m') {
x=s.top();s.pop();
y=s.top();s.pop();
t=x>y?x:y;
s.push(t);
i-=2;
}
else if(a[i]=='n'&&a[i-1]=='i'&&a[i-2]=='m') {
x=s.top();s.pop();
y=s.top();s.pop();
t=x>y?y:x;
s.push(t);
i-=2;
}
}
printf("%d\n",s.top());
}
return 0;
}
D 走迷宫
二分求最大值最小,要处理的地方是一开始就要确定上限和下限。
牛客上有原题:迷阵
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;
#define mk make_pair
const int inf=0x3f3f3f3f;
const int N=205;
typedef long long ll;
int n,m,ans;
int hy[4][2]={0,1,0,-1,1,0,-1,0};
struct node{
int x,y;
}s,t;
int a[N][N];
int bfs(int l,int r){
queue<node>q;
q.push((node){1,1});
int vis[N][N]={0};
vis[1][1]=1;
while(!q.empty()){
t=q.front();q.pop();
if(t.x==n&&t.y==n) return 1;
for(int i=0;i<4;i++){
s.x=t.x+hy[i][0];
s.y=t.y+hy[i][1];
if(s.x>=1&&s.y>=1&&s.x<=n&&s.y<=n&&vis[s.x][s.y]==0){
if(a[s.x][s.y]>=l&&a[s.x][s.y]<=r){
vis[s.x][s.y]=1;
q.push(s);
}
}
}
}
return 0;
}
int main()
{
int i,j,k;
scanf("%d",&n);
int mx=0,mi=inf;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
scanf("%d",&a[i][j]);
if(a[i][j]>mx) mx=a[i][j];
if(a[i][j]<mi) mi=a[i][j];
}
}
int l=0,r=mx;//起始位置要从0开始!!!
while(l<=r){
int mid=(l+r)/2;
int flag=0;
for(i=0;i+mid<=mx;i++){
if(a[1][1]>=i&&a[1][1]<=i+mid&&bfs(i,i+mid)) {
flag=1;
break;
}
}
if(flag) r=mid-1;
else l=mid+1;
}
printf("%d",l);
return 0;
}
E 宝物(待补)
F SUBSTRING
求最长的子串翻转后原串不变,容易错误理解成求最长回文串。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=5e4+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans,st,en;
int main()
{
int i,j,k,x,y,z;
string ans,s;
cin>>n;
while(n--){
ans="";
cin>>s;
int len=s.length();
for(i=0;i<len;i++){
for(j=1;j<=len-i;j++){
string temp=s.substr(i,j);
reverse(temp.begin(),temp.end());
if(s.find(temp)!=-1&&temp.length()>ans.length()){
reverse(temp.begin(),temp.end());
ans=temp;
}
}
}
cout<<ans<<endl;
}
return 0;
}
G BOBSLEDDING
做的时候知道是多出来的速度/2+上限速度,但是就是处理不好-_-||。
洛谷上有原题:P2968 [USACO09DEC]Bobsledding S
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=505;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans;
struct node{
int t,s;
}s[N];
int cmp(node x,node y){
return x.t<y.t;
}
int main()
{
int i,j,k,x,y,L;
scanf("%d %d",&L,&n);
for(i=1;i<=n;i++){
scanf("%d %d",&s[i].t,&s[i].s);
}
sort(s+1,s+1+n,cmp);
for(i=n-1;i>=1;i--){//如第一个点是7 3,第二个点8 1,距离上一个点是1,但是变化的距离是2,
//所以此时的点7的限制值应当进一步减小,所以第一个点应是7 2
s[i].s=min(s[i].s,s[i+1].s+s[i+1].t-s[i].t);
}
int spd=1;
for(i=1;i<=n;i++){
if(s[i].s>=spd+(s[i].t-s[i-1].t)){
spd+=(s[i].t-s[i-1].t);
ans=max(ans,spd);
}
else {
int t=spd+(s[i].t-s[i-1].t-(spd-s[i].s))/2;
ans=max(ans,t);
spd=s[i].s;
}
}
spd+=L-s[n].t;
ans=max(ans,spd);
printf("%d",ans);
return 0;
}