这个题比赛的时候没有搞出来,当时思路太乱了,而且样例都没仔细看,就开始敲了,导致敲完了看样例才发现题意理解错了,T_T
问1: 抽象成给你n(你<=15)个物品 (物品的体积为C[ i ]) ,问至少用几个箱子把这n个物品装满
问2: 预处理出一个人在服务时间小于等于m的情况下,服务集合为state 的最短行走距离,然后就和问1一样背包就行了
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
int d[16][16],c[16],n,m;
int dp1[1<<16],dp2[1<<16],x[16],y[16];
int ans[1<<16],sum[1<<16],dp[1<<16][16];
bool vis[1<<16][16];
int solve1()
{
dp1[0]=0;
for(int i=1;i<(1<<n);i++)
{
int tmp=0;
for(int j=0;j<n;j++)
if(i&(1<<j)) tmp+=c[j];
if(tmp<=m) dp1[i]=1;
else dp1[i]=-1;
}
int lim=(1<<n)-1;
for(int i=0;i<(1<<n);i++)
if(dp1[i]>=0){
int sub=i^lim;
for(int j=sub;j;j=(j-1)&(sub))
if(dp1[j]>=0){
if(dp1[i|j]==-1||dp1[i|j]>dp1[i]+dp1[j]) dp1[i|j]=dp1[i]+dp1[j];
}
}
return dp1[lim];
}
int solve2()
{
memset(sum,0,sizeof(sum));
for(int i=1;i<(1<<n);i++)
for(int j=0;j<n;j++)
if(i&(1<<j)) sum[i]+=c[j];
queue<pair<int,int> > q;
q.push(make_pair(0,0));
memset(vis,0,sizeof(vis));
memset(dp,-1,sizeof(dp));
dp[0][0]=c[0];
for(;!q.empty();q.pop())
{
int s=q.front().first,u=q.front().second;
vis[s][u]=0;
for(int j=0;j<n;j++)
if(!(s&(1<<j))&&sum[s|(1<<j)]<=m){
if(dp[s|(1<<j)][j]==-1||dp[s|(1<<j)][j]>dp[s][u]+d[u][j]){
dp[s|(1<<j)][j]=dp[s][u]+d[u][j];
if(!vis[s|(1<<j)][j]) q.push(make_pair(s|(1<<j),j)),vis[s|(1<<j)][j]=1;
}
}
}
memset(ans,-1,sizeof(ans));
for(int i=0;i<(1<<n);i++)
for(int j=0;j<n;j++)
if(dp[i][j]!=-1){
if(ans[i]==-1||ans[i]>dp[i][j]+d[j][0]) ans[i]=dp[i][j]+d[j][0];
}
ans[0]=0;
int lim=(1<<n)-1;
for(int i=0;i<(1<<n);i++)
if(ans[i]>=0)
{
int sub=lim^i;
for(int j=sub;j;j=(j-1)&(sub))
if(ans[j]>=0){
if(ans[i|j]==-1||ans[i|j]>ans[i]+ans[j]) ans[i|j]=ans[i]+ans[j];
}
}
return ans[lim];
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
for(int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);
for(int i=0;i<n;i++) scanf("%d",&c[i]);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) d[i][j]=ceil(sqrt((x[i]-x[j])*(x[i]-x[j])*1.0+(y[i]-y[j])*(y[i]-y[j])*1.0));
int i;
for(i=0;i<n;i++)
if(c[i]>m) break;
if(i<n){
printf("-1 -1\n");
}else printf("%d %d\n",solve1(),solve2());
}
return 0;
}