题目:
有n个商店,通过m条双向道路连接,通过道路需要时间。
你可以在编号为0至p-1的商店里购买物品。为了在第i号商店购买物品,你需要在[li,ri]范围内的某一时间开始一次购买(包括时刻li和时刻ri),购买持续ti个时刻。你只能在每个商店购买一次物品。
在0时刻你位于编号为n-1的商店,你需要求出你最多能购买多少物品。你可以在一个商店逗留.
第一行三个整数,表示n,p,m
接下来行,第行三个整数,表示li,ri,ti
接下来行,每行三个整数,a,b,c表示有一条双向道路连接a,b,通过时间为c
输出仅一行,一个整数,表示最多能购买的物品数
数据范围1<=n,m<=50;1<=p<=min(16,n),1<=ci<=604800,0<=li<ri<=604800,1<=ti<=604800
不知道为什么有很少的测试点我的代码输出的答案比标准答案大1~2 代码如下
#include<bits/stdc++.h>
using namespace std;
int h[110],e[110],ne[110],w[110],idx;
void add(int a,int b,int c){
e[++idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx;
}
int l[60],r[60],ti[60];
int dp[65536][51];
bool st[65536][51];
int n,m,p;
typedef pair<int,int>PII;
void bfs(){
queue<PII>q;
q.push({0,n});
dp[0][n]=0;
st[0][n]=1;
while(q.size()){
PII t=q.front();q.pop();
st[t.first][t.second]=0;
for(int i=h[t.second];i;i=ne[i]){
int j=e[i];
if(dp[t.first][j]>dp[t.first][t.second]+w[i]){
dp[t.first][j]=dp[t.first][t.second]+w[i];
if(!st[t.first][j]){
q.push({t.first,j});
st[t.first][j]=1;
}
}
if(j<p){
if(!(t.first&(1<<j))){
int tb;
if(dp[t.first][t.second]+w[i]>=l[j]){
tb=dp[t.first][t.second]+w[i];
}
else{
tb=l[j];
}
if(tb<=r[j]){
int te=dp[t.first][t.second]+w[i]+ti[j];
int nexstate=t.first|(1<<j);
if(dp[nexstate][j]>te){
dp[nexstate][j]=te;
if(!st[nexstate][j]){
st[nexstate][j]=1;
q.push({nexstate,j});
}
}
}
}
}
}
}
}
int _1cnt(int x){
int ans=0;
for(int i=0;i<p;i++){
if(x&(1<<i)) ans++;
}
return ans;
}
int main(){
scanf("%d%d%d",&n,&p,&m);
for(int i=0;i<p;i++) scanf("%d%d%d",&l[i],&r[i],&ti[i]);
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
add(n,n-1,0);
memset(dp,0x3f,sizeof dp);
bfs();
int ans=0;
for(int i=0;i<(1<<p);i++){
for(int j=0;j<n;j++){
if(dp[i][j]<0x3f3f3f00) ans=max(ans,_1cnt(i));
}
}
printf("%d\n",ans);
return 0;
}
92pts