河南省第四届ACM/ICPC大学生程序设计竞赛题解

第四届河南省大学生程序设计竞赛

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;
}

H Interesting Punch-Bowl(待补)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值