Problem N

简单题意

是n个发电站,m条路,每条路有各自的距离,每个发电站有各自的发电量,现在需要炸毁它们,一辆坦克只能炸毁一个发电站,而且需要炸毁的发电厂的发电量需要大于所有发电站所产生的总电量的一半,求坦克走的最短距离。

解题思路形成过程

因为题目说明不超过100个点,所以可以用floyd算法,不过因为用了三重循环,算法复杂度会增加,一不小心就超时,用cin的话就会超时,必须用scanf。把所有的0到各个发电站的距离找出来,然后把0能到的各个发电站的距离相加作为背包的容量,以dp数组储存的值作为炸毁的发电站的电量,最后进行判断,如果dp[i]的值大于所有发电站的总电量,输出i的值,此时i的值就是坦克炸毁发电站使城市供电瘫痪所能走的最短距离。

感想

floyd算法虽然写起来很简单,不过容易超时,况且这道题还加上了一些dp的内容。

AC代码

#include
#include
#include
#include
using namespace std;
#define INF 0x3f3f3f3f
int map[305][305];
int n,m;
int a[10010];
int dp[100001];
void floyd(){
    for(int k=0;k<=n;k++){
        for(int i=0;i<=n;i++){
            for(int j=0;j<=n;j++){
                if(map[i][j]>map[i][k]+map[k][j]){
                    map[i][j]=map[i][k]+map[k][j];
                }
            }
        }
    }
}
int main()
{
    ifstream cin("in.txt");
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++){
            for(int j=0;j<=n;j++){
                map[i][j]=INF;
            }
            map[i][i]=0;
        }
        int x,y,z;
        for(int i=0;i             scanf("%d%d%d",&x,&y,&z);
            if(map[x][y]>z){
                map[x][y]=z;
                map[y][x]=z;
            }
        }
        floyd();
        int sum=0;
        int count=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum+=a[i];
            if(map[0][i]!=INF){
                count+=map[0][i];
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){
            for(int j=count;j>=map[0][i];j--){
                if(dp[j-map[0][i]]+a[i]>dp[j]){
                    dp[j]=dp[j-map[0][i]]+a[i];
                }
            }
        }
        int flag=0;
        for(int i=1;i<=count;i++){
            if(dp[i]>sum/2.0){
                flag=1;
                printf("%d\n",i);
                break;
            }
        }
        if(flag==0){
            printf("impossible\n");
        }
    }
    return 0;
}

你可能感兴趣的:(2016SDAU课程练习四)