背包判无解及输出方案求助
查看原帖
背包判无解及输出方案求助
239895
Yusani_huh楼主2022/11/16 10:06

自己看过了,找同学看过了,还重构了一遍,就是没发现有什么问题,求助。

#include<bits/stdc++.h>
using namespace std;
#define N 100003
#define LL long long
#define INF 0x3f3f3f3f
int T,n,m,ed[N],asl[N];
LL a[N],dp[203];
struct plan{
	int e,p,id;
	LL t;
}p[N];
struct node{
	int nw,ls,ln;
}pr[203];
bool cmp(plan a,plan b){
	if(a.e!=b.e) return a.e<b.e;
	return a.t<b.t;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;++i)
			scanf("%lld",&a[i]);
		for(int i=1;i<=m;++i)
			scanf("%d%lld%d",&p[i].e,&p[i].t,&p[i].p),
			p[i].id=i;
		p[m+1]={0,0,0,0};
		sort(p+1,p+m+1,cmp);
		for(int i=1;i<=m;++i) //分出所有任务
			if(p[i].e!=p[i+1].e) ed[p[i].e]=i;
		LL sm=0;
		int nw=1,fl=0,tot=0;
		for(int i=1;i<=n;++i){
			LL ans=INF;
			int ni=0,nj=0;
			memset(dp,0x3f,sizeof dp);
			dp[0]=0;
			for(;nw<=ed[i];++nw){
				int pp=p[nw].p;
				for(int j=200;j>=pp;--j){ //一个平凡的背包记录方案
					if(dp[j-pp]+p[nw].t<dp[j])
						dp[j]=dp[j-pp]+p[nw].t,
						pr[j]={nw,j-pp,pr[j-pp].nw};
					if(j>=100&&dp[j]<ans) //如果当前在100及以上那么记录答案
						ans=dp[j],nj=j,ni=nw;
				}
			}
			sm+=ans;
			if(sm>a[i]){fl=1;break;} //若不能按时完成则-1
			while(nj) //输出方案,之前记的ln用来避免重复
				asl[++tot]=p[ni].id,
				ni=pr[nj].ln,nj=pr[nj].ls;
		}
		if(fl){puts("-1");continue;}
		printf("%d\n",tot);
		for(int i=1;i<tot;++i)
			printf("%d ",asl[i]);
		printf("%d\n",asl[tot]);
	}
	return 0;
}

这份代码在第 3 个点的第 2169 个数据,第 17 个点的第 3953,6237 个数据显示没有按时完成所有任务,在第 17 个点的第 2063,3407,5848 个数据显示我使用的操作数多于他给出的 mm。经我测试这几个点答案都是 -1,也就是代码里判无解出现了问题。

还有第 20 个点的第 183 个数据显示我的操作没有完成所有任务,并且这个点答案并不是 -1,但我据代码找不到 dp 部分有什么问题,猜测是输出方案出错。

2022/11/16 10:06
加载中...