SOJ 4543 4542

http://acm.scu.edu.cn/soj/problem.action?id=4542

递归用数组保存中间值

#include <cstdio>  
#include <cmath>  
#include <cstring>  
#include <algorithm>  
#include <iostream>  
typedef long long ll;
using namespace std; 
ll ans[55][55];
ll F(int n,int m){
    if(ans[n][m]!=0) return ans[n][m];
    if(n==0||m==0) return 0;
    ans[n][m]=F(n-1,m-1)+F(n,m-1) + 1;
    return ans[n][m];
};
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        printf("%lld\n",F(n,m));
    }
    return 0;
}

4542:从RE---MLE--WA--MLE--AC 曲折之路,获得教训,1.数组大小尽量大,也要尽量小 2.循环的次数:只循环必须要循环的  3.建完全图一定要各个点之间都双向且有距离 4.图无非点和边 Dijskra中循环次数主要是n (点的个数) 所以一定要搞清题目中规定的点的个数的上限!

AC还是非常激动~~

#include <stdio.h>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAX 0x3f3f3f3f;
const long long N=2e3+4;
//const long long NN=1e6;
struct E{
    int next;
    int c;
};
vector<E> edge[N];
bool mark[N];
long long Dis[N];
int x[N],y[N];//坐标
void addedge(int x,int y,int c){
                E tmp;
                tmp.c=c;tmp.next=x;
                edge[y].push_back(tmp);
                tmp.next=y;
                edge[x].push_back(tmp);
};
int dis(int x1,int y1,int x2,int y2){
    return abs(x1-x2)+abs(y1-y2);
};
int main(){
    int n,m,t,k,st,stx,sty;
    scanf("%d",&t);
    int f=3;//终点
    while(t--){
        scanf("%d%d%d",&n,&m,&k);
        int xuhao=4;
        int f2=1;int tol=0;
        for(int i=1;i<=N;i++) edge[i].clear();
        scanf("%d%d",&stx,&sty);
        //st=(stx-1)*m+sty; 想着二维转换为一维,但是太大了,也不需要用到这么多数,只加有用的点
        st=2;
        addedge(st,f,dis(n,m,stx,sty));
        x[1]=1;y[1]=1;x[2]=stx;y[2]=sty;x[3]=n;y[3]=m;
        //cout<<dis(n,m,stx,sty)<<" *** ";
        addedge(st,1,dis(1,1,stx,sty));
        tol+=3;
        while(k--){
            int x1,y1,x2,y2,c,s1,s2;
            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
            //s1=(x1-1)*m+y1;s2=(x2-1)*m+y2;
            s1=xuhao++;s2=xuhao++;
            x[s1]=x1;y[s1]=y1;x[s2]=x2;y[s2]=y2;
            /*错误版本,加边 构成完全图
            addedge(s1,s2,c);
            addedge(s1,st,dis(stx,sty,x1,y1));
            addedge(s2,st,dis(stx,sty,x2,y2));
            addedge(s1,f,dis(n,m,x1,y1));
            addedge(s2,f,dis(n,m,x2,y2));
            addedge(s1,1,dis(1,1,x1,y1));
            addedge(s2,1,dis(1,1,x2,y2));
            */
            addedge(s1,s2,c);
            for(int i=1;i<xuhao-2;i++){
                addedge(s1,i,dis(x[i],y[i],x1,y1));
                addedge(s2,i,dis(x[i],y[i],x2,y2));
            }
            tol+=2;
        }
        for(int i=1;i<=tol;i++){
            Dis[i]=-1;
            mark[i]=false;
        }
        Dis[st]=0;mark[st]=true;
        int newp=st;
        for(int i=1;i<tol;i++){//循环 点数-1 次
            for(int j=0;j<edge[newp].size();j++){//遍历相邻节点
                int t=edge[newp][j].next;
                //cout<<"相邻节点: "<<t<<" *** ";
                int c=edge[newp][j].c;
                if(mark[t]==true) continue;
                if(Dis[t]==-1||Dis[t]>Dis[newp]+c)  Dis[t]=Dis[newp]+c;
            }
            int min=MAX;
            for(int j=1;j<=tol;j++){ //遍历V中节点找最小值,以加入K集合
                if(mark[j]==true) continue;
                if(Dis[j]==-1) continue;
                if(Dis[j]<min){
                    min=Dis[j];
                    newp=j;
                }
            }
            mark[newp]=true;
        }
        printf("%lld\n",min(Dis[1],Dis[3]));
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值