用一个二进制记录当前状态。
二进制中的0代表当前点已经被走过,1代表当前点还未走过。
如果当前二进制之前计算过,且值大于当前值的话,那么就终止不走。
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; int shuyu[5001]; int n; int w[101][101]; int e[101][101]; int s[101]; int dp[5001]; void init() { int ns=1; for(int i=1;i<=12;i++) { shuyu[ns]=i; ns=ns*2; } for(int i=1;i<=5000;i++)if(shuyu[i]==0)shuyu[i]=shuyu[i-1]; } void dos(int num,int exp,int as) { //cout<<num<<" "<<exp<<" "<<as<<endl; if(num<dp[as])return ; dp[as]=num; if(as==0)return; int st; st=as; int ed; ed=as; while(ed) { st=ed&(ed-1); st=ed-st; int pp=shuyu[st]; if(exp>s[pp])dos(num+w[1][pp],exp+e[1][pp],as-(1<<(pp-1))); else dos(num,exp+e[1][pp],as-(1<<(pp-1))); ed=ed-st; } } int main() { int _,i,j; init(); scanf("%d",&_); while(_--) { memset(dp,0,sizeof(dp)); scanf("%d",&n); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { scanf("%d",&e[i][j]); } } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { scanf("%d",&w[i][j]); } } for(i=1;i<=n;i++) { scanf("%d",&s[i]); } int as=0; int ns=1; for(i=1;i<=n;i++) { as+=(1<<(i-1)); } as-=1; int leap=1; int ans=0; while(leap) { leap=0; for(i=2;i<=n;i++) { if(s[1]<=s[i])continue; if((1<<(i-1))&as) { s[1]+=e[1][i]; as-=(1<<(i-1)); ans+=w[1][i]; leap=1; } } } if(as==0)cout<<ans<<endl; else { dp[as]=ans; dos(ans,s[1],as); cout<<dp[0]<<endl; } } }