题目链接:https://ac.nowcoder.com/acm/contest/104637/E
题意:
在给定的数组中选出一些数,组成封闭凸多边形周长最小
思路:
注意到:最长边<其他所有边之和
不妨枚举最长边,再对小于它的边进行背包dp,以此来求解
dp数组的0/1状态分别表示:其他边(总长为j)此时可以转移得到
背包初始化dp[0]=1,枚举其他边总长(big+1,1e4),如果dp[j]=1,即可以通过01背包得到,立刻取min并break
从后往前枚举,发现dp[p]可以由dp[p-a[i]]转移得到,即如果dp[p-a[i]]可以得到,那么dp[p]也可以得到
void solve(){int n;cin>>n;vector<int>a(n+1);for(int i=1;i<=n;i++)cin>>a[i];sort(a.begin()+1,a.end());vector<int>dp(maxn);dp[0]=1;int ans=1e9;for(int i=1;i<=n;i++){int big=a[i];for(int j=big+1;j<=1e4;j++){if(dp[j]){ans=min(ans,j+big);break;}}for(int p=1e4;p>=big;p--){dp[p]|=dp[p-a[i]];} }if(ans>1e8)cout<<-1<<endl;else cout<<ans<<endl;
}