深搜(2) 寻路 蛋糕

ROADS (POJ1724)
N个城市,编号1到N。城市间有R条单向道路。
每条道路连接两个城市,有长度和过路费两个属性。
Bob只有K块钱,他想从城市1走到城市N。问最短共需要走多长的路。如果到不了N,输
出-1
2<=N<=100
0<=K<=10000
1<=R<=10000
每条路的长度 L, 1 <= L <= 100
每条路的过路费T , 0 <= T <= 100
输入:
K
N
R
s 1 e 1 L 1 T 1
s 1 e 2 L 2 T 2

s R e R L R T R
s e是路起点和终点
Sample Input
5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2
Sample Output
11

#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
struct rode
{
    int d;int l;int t;
};
int minlen=1<<30,tallen,talcost;//当前最优路径长度,正在走的路的长度,花销
vector<vector<rode> > cityway(105);//cityway[i]是从i有路连接到的城市集合,二维数组
int visited[105];//判重标记,visited[i]=ture,表示i已经走过
int minl[105][10005];//minl[i][j]表示从1到i的,花销为j的最短路长度
int k,n,r;
void dfs(int s)//从s开始想n行走
{
    if(s==n)
    {
        minlen=min(minlen,tallen);//更新最小值
        return ;
    }
    for (int i=0;i<cityway[s].size();i++)
    {
        int d=cityway[s][i].d;//s有路连到d
        if(!visited[d])
        {//没走过的
            int cost=cityway[s][i].t+talcost;
            if (cost>k) continue;//剪枝
            if (tallen + cityway[s][i].l>=minlen|| tallen+cityway[s][i].l>=minl[d][cost])//最优性剪枝
                continue;
            visited[i]=1;
            tallen+=cityway[s][i].l;
            talcost+=cityway[s][i].t;//更新数据
            minl[d][cost]=tallen;
            dfs(d);//从这路的终点再出发
            visited[i]=0;//上个点不符合,则将上个点的数据清除
            tallen-=cityway[s][i].l;
            talcost-=cityway[s][i].t;
        }
    }
}
int main()
{
    cin>>k>>n>>r;
    for (int i=0;i<r;i++)
    {
        int s;
        rode r;
        cin>>s>>r.d>>r.l>>r.t;
        if (s!=r.d)//起点和终点不同
            cityway[s].push_back(r);//把r压进容器
    }
    for (int i=0;i<105;i++)
    {
        for(int j=0;j<10005;j++)
            minl[i][j]=1<<30;//初始化为最大值无穷大
    }
    memset(visited,0,sizeof(visited));//标志清零
    tallen=0; talcost=0;
    minlen=1<<30;
    visited[1]=1;//第一个走过
    dfs(1);
    if(minlen<(1<<30))//若改变了,比最大值小
        cout<<minlen<<endl;
    else cout<<"-1"<<endl;
    return 0;
}

生日蛋糕 (POJ1190)
Description
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)
Input
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
Output
仅一行,是一个正整数S(若无解则S = 0)。
Sample Input
100
2
Sample Output
68
Hint
圆柱公式
体积V = πR2H
侧面积A’ = 2πRH
底面积A = πR2

#include <iostream>
#include <cstring>
#include <cmath>
#include <stdlib.h>
using namespace std;
int n,m;
int area;//正在搭建的面积
int minarea=1<<30;//最优表面积
int minv[25];//minv[i],i层蛋糕最少的体积
int mina[25];//mina[i]i层蛋糕最少侧面积
int maxf(int n,int r,int h)
{
    int v=0;
    for (int i=0;i<n;i++)
    v+=(r-i)*(r-i)*(h-i);//最大半径,高度,最大体积
    return v;
}
void dfs(int v,int n,int r,int h)
{//要用n层去凑体积v,最底层半径不能超过r,高度不能超过h
    if (n==0)
    {//到顶了
        if(v) return ;
        else 
        {
            minarea=min(minarea,area);//更新最小值
            return;
        }
    }
    if (v<=0) return ;//体积不存在
    if(h<n||r<n) return;//最大半径,高度比层数小(最小半径高度)
    if(minv[n]>v) return ;//当前体积小于最小体积
    if(mina[n]+area>=minarea) return ;//当前面积比最小面积要大,剪枝
    if(maxf(n,r,h)<v)
        return ;//当前最大体积比要求的小
    for (int rr=r;rr>=n;rr--)
        {
            if (n==m) area=rr*rr;//层数到了,底面积
                for(int hh=h;hh>=n;hh--)
                {
                    area+=hh*rr*2;//侧面积
                    dfs(v-rr*rr*hh,n-1,rr-1,hh-1);//减去当前体积剩的,层数-1,
                    area-=hh*rr*2;//不符合减去
                }
        }
}

int main()
{
    cin>>n>>m;
    minv[0]=0;
    mina[0]=0;
    for (int i=1;i<=m;i++)
    {
        minv[i]=minv[i-1]+i*i*i;//第i层半径至少为i,高度至少为i;
        mina[i]=mina[i-1]+2*i*i;//2*pai*r*h
    }
    if (minv[m]>n)
        cout<<0<<endl;
    else 
    {//(总体积-最小体积)/最小半径*m,加一,为了向上取整
        int maxh=(n-minv[m-1])/(m*m)+1;//底层最大高度
        int maxr=sqrt((double)(n-minv[m-1])/m)+1;//底层最大半径
        area=0; minarea=1<<30;
        dfs(n,m,maxr,maxh);
        if (minarea==1<<30)//未曾改变
            cout<<0<<endl;
        else cout<<minarea<<endl;
    }
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40823992/article/details/81744417