A: AKU NEGARAKU
给出一个数组,从第一个开始走,每走m个就把该数删除。
由于n很小,直接模拟就好了。
int main(){
int n,m;
while(cin>>n>>m){
if(!n)break;
queue<int> q;
for(int i = 1; i <=n; ++i)q.push(i);
while(!q.empty()){
if(q.size()==1)break;
for(int i= 0; i < m-1; ++i){
q.push(q.front());
q.pop();
}
q.pop();
}
cout<<q.front()<<endl;
}
}
B: CHEAP DELIVERIES
给出一个n个点m条边的图,然后有k条线路,每条线路从某个点到某个点,问怎么安排使得总路径最短。
由于k只有18,可直接状态压缩dp。
但是因为n是10^4,存不下n^n的距离,需要只记录需要的点之间的路径。
int dp[1<<20][20];
vector<pair<int,int>> g[10010];
int tmp_dis[20000];
int v[200][200];
int f[200],d[200];
int get_min(int a, int b){
if(a==-1)return b;
if(b==-1)return a;
return min(a,b);
}
void bfs(int u){
queue<int> q;
q.push(u);
memset(tmp_dis,-1,sizeof(tmp_dis));
tmp_dis[u] = 0;
while(!q.empty()){
int t = q.front();q.pop();
for(auto r : g[t]) {
int v = r.first;
int c = r.second;
if(tmp_dis[v]==-1 || tmp_dis[v]>tmp_dis[t]+c){
tmp_dis[v] = tmp_dis[t]+c;
q.push(v);
}
}
}
}
int main(){
int n,m,k;
cin>>n>>m>>k;
for(int i = 0; i < m; ++i){
int u,v,l;
cin>>u>>v>>l;
g[u].push_back(make_pair(v,l));
g[v].push_back(make_pair(u,l));
}
set<int> nodes;
vector<int> idx;
for(int i = 0; i < k; ++i){
cin>>f[i]>>d[i];
nodes.insert(f[i]);
nodes.insert(d[i]);
}
map<pair<int,int>,int> dis;
for(int u : nodes){
bfs(u);
for(int v:nodes){
dis[make_pair(u,v)] = tmp_dis[v];
}
}
memset(v,-1,sizeof(v));
memset(dp,-1,sizeof(dp));
for(int i = 0; i < k; ++i){
for(int j = 0; j < k; ++j){
int u = f[j],u1 = d[j], u2 = d[i];
if( dis[make_pair(u,u1)]==-1)continue;
if( dis[make_pair(u2,u)]==-1) continue;
v[i][j] = dis[make_pair(u,u1)]+dis[make_pair(u2,u)];
}
int u = f[i],v = d[i];
if(dis[make_pair(u,v)]==-1)continue;
dp[1<<i][i] = dis[make_pair(u,v)];
}
for(int i = 0; i< 1<<k;++i){
for(int j = 0; j < k; ++j){
if(dp[i][j]==-1)continue;
for(int jj = 0; jj < k; ++jj){
if((i>>jj)&1)continue;
if(v[j][jj]==-1)continue;
dp[i|(1<<jj)][jj] = get_min(dp[i|(1<<jj)][jj],dp[i][j]+v[j][jj]);
}
}
}
int ans = -1;
for(int i = 0; i < k; ++i){
if(dp[(1<<k)-1][i]==-1)continue;
ans = get_min(ans, dp[(1<<k)-1][i]);
}
cout<<ans<<endl;
}
C: ELI'S CURIOUS MIND
给出[1,n]的数,从里面不断拿出一个数,这个数不能和已经拿到的数相邻,直到不能拿为止。问有多少种不同的结果。
由于是不断的拿,因此第一个数肯定是1或者2,最后一个数肯定是n或者n-1
dp预处理 dp[i] = dp[i-1]+dp[i-2]
int dp[100];
int main(){
dp[1]=1;
dp[2]=1;
for(int i = 3; i<=76;++i){
dp[i] = dp[i-2] + dp[i-3];
}
dp[1]=0;dp[2]=0;
int n;
int c = 1;
while(cin>>n && n){
printf("Case #%d: %d\n",c++,dp[n]+dp[n-1]);
}
}
D: EXPLORACE
最小生成树
E: MATRIX MULTIPLICATION CALCULATOR
矩阵乘法
F: SUM OF SUB RECTANGLE AREAS
把r和c换个位置就变成
而前后两项是独立而且值是一样的。那么只需要计算其中一个就可以了
其中一项就是 对于c1固定时,和就是 i*(i+1)/2, (i=n-c1)
那么变成
G: WAK SANI SATAY
看不懂题目
H: STROOP EFFECT
看不懂题目啊!!!
I: SUPER BALL
还是看不懂啊,能不能说的简单点啊。
貌似是个简单dp,有空再补
斐波拉数列 + 大数
本文解析了多个算法题目,包括数组操作、最短路径、动态规划等,通过具体实例介绍了如何设计高效算法解决实际问题。
424

被折叠的 条评论
为什么被折叠?



