恩,核心是01背包,结果,我托了三个月才ac....... 结果发现,是容斥定理用错了。。。这几天,我应该好好扇自己的脸。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define MAX 105
using namespace std;
int n,s,a,grid[MAX][MAX],sumgrid[MAX][MAX],sep[MAX];
int dp[MAX][MAX],amount[MAX][MAX],father[MAX][MAX];
void init(){
memset(grid,0,sizeof(grid));
memset(sumgrid,0,sizeof(sumgrid));
int aa,bb;
for(int i=0;i<n;i++){
cin>>aa>>bb;
grid[aa][bb]=1;
}
for(int i=1;i<100;i++){
for(int j=1;j<100;j++)
sumgrid[i][j]=grid[i][j]+sumgrid[i][j-1]+sumgrid[i-1][j]-sumgrid[i-1][j-1];
}
cin>>s;
for(int i=0;i<s;i++){
cin>>sep[i];
}
cin>>a;
memset(dp,0,sizeof(dp));
memset(amount,0,sizeof(amount));
for(int i=1;i<=99;i++){
for(int j=i+1;j<=100;j++){
for(int t=1;t<s;t++){
if(sumgrid[sep[t]-1][j-1]-sumgrid[sep[t]-1][i-1]-sumgrid[sep[t-1]-1][j-1]+sumgrid[sep[t-1]-1][i-1]>0)//这个地方写成了加两倍。。。
amount[i][j]++;
}
}
}
}
void print(int which,int index){
if(which==0)
return ;
print(which-1,father[index][which]);
cout<<' '<<index;
}
void solve(){
for(int i=2;i<=100;i++){
for(int j=2;j<=a&&j<=i;j++){
for(int t=i-1;t>=1&&t>=j-1;t--){
if(dp[t][j-1]+amount[t][i]>=dp[i][j]){
dp[i][j]=amount[t][i]+dp[t][j-1];
father[i][j]=t;
}
}
}
}
cout<<a;
print(a,100);
cout<<endl;
}
int main(){
while(cin>>n&&n!=-1){
init();
solve();
}
return 0;
}