Ingress (TSP问题+floy预处理)

Ingress

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 102400/65535 K (Java/Others)
Total Submission(s): 440    Accepted Submission(s): 205


 

Problem Description

Brickgao, who profited from your accurate calculating last year, made a great deal of money by moving bricks. Now he became ``gay shy fool'' again and recently he bought an iphone and was deeply addicted into a cellphone game called Ingress. Now he is faced with a problem so he turns to you for help again. We make some slight modifications based on the original rules, so please draw attention to the details below.

There are  portals (indexed from 1 to ) around Brickgao's home, and he can get some substances called XM by hacking the portals. It's known that for each portal , he can get  XM during the first hack, and after each hack, the amount of XM he will get during the next hack will decrease by . If the amount of XM he can get is less than or equal to zero, Brickgao can't get XM from that portal anymore. For the -th portal, if  and he hacks 3 times, he will get 10, 8, 6 XM during each hack.

There are  bidirectional roads between some pairs of portals and between Brickgao's home and some portals. Now he is eager to start his Ingress journey from home and finally return home, but due to the extremely hot weather, Brickgao will feel sick when you hack more than  times or the distance he covers is more than . So how much XM he can get at most during this journey?
 

Input

The first line contains a single integer , indicating the number of test cases.

The first line of each case are four integers  and .
The second line of each case contains  non-negative integers where the -th denotes .
The third line of each case contains  non-negative integers where the -th denotes .
Each of next  line contains 3 non-negative integers  and  , denotes that there is a road with the length of  between the -th and the -th portal. If  or  equals to 0, it means Brickgao's home.

Output

For each test case, output the case number first, then the amount of maximum XM Brickgao can get.

Sample Input

 

2 1 1 3 2 5 3 0 1 1 3 6 3 5 10 7 5 2 3 1 0 1 3 0 2 1 0 3 1 1 2 2 2 3 3 1 3 4

Sample Output

 
#include<stdio.h>
#include <algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<deque>
#include<ctype.h>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
//inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
int a[25],b[25];
int d[25][25];
int dp[1<<17][25];

typedef pair<int,int>P;
void floyd(int n)
{
    for(int k=0;k<=n;k++)
    {
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
            {
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
}
int main()
{
    int n,m,k,l;
    int tt,Case=0;
    scanf("%d",&tt);
    while(tt--)
    {
        scanf("%d%d%d%d",&n,&m,&k,&l);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        memset(d,0x3f,sizeof(d));
        memset(dp,0x3f,sizeof(dp));
        for(int i=1;i<=m;i++)
        {
            int x,y,c;
            scanf("%d%d%d",&x,&y,&c);
            if(d[x][y]>c)
                d[x][y]=d[y][x]=c;
        }
        floyd(n);///处理最短路。
        dp[1][0]=0;
        for(int i=0;i<(1<<(n+1));i++)///二进制枚举所有状态。
        {

            for(int j=0;j<=n;j++)///i状态中是否到过(1<<j)点
            {
                if(i&(1<<j))
                {
                    for(int t=0;t<=n;t++)
                    {
                        if((1&(1<<t))==0) ///i状态没到过的点要加上。
                            dp[i|(1<<t)][t]=min(dp[i|(1<<t)][t],dp[i][j]+d[j][t]);
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;i<(1<<(n+1));i++)
        {
            int flag=0;
            for(int j=0;j<=n;j++)
            {
                if(i&(1<<j) && dp[i][j]+d[j][0]<=l)///到过该点,并从该点返回起点距离是否超过l。
                    flag=1;
            }
            if(!flag)
                continue;
            int temp=0;
            priority_queue<P>q;///优先队列取值,将a[i],b[i]用pair联系放到队列中。
            for(int t=0;t<=n;t++)
            {
                if(i&(1<<t))///经过的点都放到队列中。
                    q.push(P(a[t],b[t]));
            }

            for(int t=0;t<k && !q.empty();t++)///最多取k次。
            {
                P pp=q.top();
                q.pop();
                temp=temp+pp.first;///加上权值a[i]。
                pp.first-=pp.second;///减去b[i]。
                q.push(pp);///再放回队列中。
            }
            ans=max(temp,ans);
        }
        printf("Case %d: %d\n",++Case,ans);
    }
    return 0;
}

Case 1: 7 Case 2: 16

Source

"巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场

题意:有n+1个点,m条边,起点为0,除了0外其它点都有一个权值,一个人从0出发到达每一个点,再回到0。到达i点可以取i的权值a[i],取后权值将减少b[i]。最多可以取k次权值,并且总路程不能超过l。问最多能趣取到多少。

分析:首先是一个典型的TSP(商人旅行问题),拿状压dp跑一下,在此之前要对输入处理一下,拿floyd处理一下。最后再对l,k进行判断就行了。

猜你喜欢

转载自blog.csdn.net/ToBeYours/article/details/81151456