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