33,010
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
//最长递减自序列。。。
int main(int argc, char **argv)
{
int arr[10001];
int subMax[10001];
int nb;
while(1)
{
scanf("%d",&nb);
if(nb==0)
break;
for(int i=0; i<nb; ++i)
scanf("%d",&arr[i]);
subMax[nb-1] = 1;
for(int i=nb-2; i>=0; --i)
{
subMax[i] = 1;
for(int j=i+1; j<nb; ++j)
{
if(arr[i]>=arr[j])
{
if(subMax[j]+1>subMax[i])
subMax[i] = subMax[j]+1;
}
}
}
printf("%d\n",subMax[0]);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
struct edge
{
int p1;
int p2;
int w;
};
int comp(const void *a, const void *b)
{
edge *arg1 =(edge*)a;
edge *arg2 =(edge*)b;
return arg1->w - arg2->w;
}
//找最小生成树,贪心法,从权值最小的边开始。
//每次加入一条边后对连接的所有顶点更新所属的子图ID
//以防止发生回路的情况,
int main(int argc, char **argv)
{
int instance;
cin>>instance;
for(int d=0; d<instance; ++d)
{
int vertNB, edgeNB;
cin>>vertNB>>edgeNB;
if(edgeNB < vertNB-1)
{
cout<<0<<endl;
continue;
}
int *vertArr = new int[vertNB];//用来记录个个顶点所属的子图ID
for(int i=0; i<vertNB; ++i)
vertArr[i] = i;//每个顶点标识不同的子图ID
edge edgeArr[100];//边的数组
for(int i=0; i<edgeNB; ++i)
{
cin>>edgeArr[i].p1>>edgeArr[i].p2>>edgeArr[i].w;
}
qsort(edgeArr, edgeNB, sizeof(edge),comp);//排序下,等下从小到大
int min = 0;
//----开始找最小生成树
for(int i=0; i<edgeNB; ++i)
{
if(vertArr[edgeArr[i].p1] != vertArr[edgeArr[i].p2])
{
min += edgeArr[i].w;
for(int j=0; j<vertNB; ++j)//更新顶点的所属子图ID
{
if(vertArr[j]==vertArr[edgeArr[i].p2])
vertArr[j] = vertArr[edgeArr[i].p2];
}
}
}
cout<<min<<endl;//最后找出来的就是了
}
return 0;
}
#include <iostream>
using namespace std;
int *pos;
int *col;
int **mar;
int c_p;
int n;
int compar (const void *a ,const void *b)
{
int *aa=(int *)a;
int *bb=(int *)b;
if(*aa>*bb)
return 1;
if(*aa==*bb)
return 0;
if(*aa<*bb)
return -1;
return 0;
}
int maxa(int a,int b)
{
return a>b? a:b;
}
int dp()
{
int max;
int **get=new int*[n];
for(int f=0;f<n;++f)
{
get[f]=new int[n];
}
get[0][n-1]=0;
for(int i=0;i<c_p;++i)
{
for(int j=n;j>=0;--j)
{
int temp1=0,temp2=0;
if(i-1>=0)
{
temp1=get[i-1][j];
}
if(j+1<n)
{
temp2=get[i][j+1];
}
get[i][j]=mar[i][j]+maxa(temp1,temp2);
}
}
max=get[0][0];
for(int h=1;h<c_p;++h)
{
if(get[h][0]>max)
{
max=get[h][0];
}
}
return max;
}
int main()
{
cin>>n;
while(n!=0)
{
col=new int[n];
pos=new int[n];
mar=new int*[n];
c_p=0;
for(int i=0;i<n;++i)
{
cin>>col[i];
bool flag=true;
for(int j=0;j<c_p;++j)
{
if(pos[j]==col[i])
{
flag=false;
break;
}
}
if(flag==true)
{
pos[c_p++]=col[i];
}
mar[i]=new int[n];
}
qsort(pos,c_p,sizeof(int),compar);
for(int k=0;k<n;++k)
{
for(int l=0;l<c_p;++l)
{
mar[l][k]=0;
if(pos[l]==col[k])
{
mar[l][k]=1;
}
}
}
cout<<dp()<<endl;
cin>>n;
}
return 0;
}
#include <iostream>
using namespace std;
int *pos;
int *col;
int **mar;
int c_p;
int n;
int compar (const void *a ,const void *b)
{
int *aa=(int *)a;
int *bb=(int *)b;
if(*aa>*bb)
return 1;
if(*aa==*bb)
return 0;
if(*aa<*bb)
return -1;
return 0;
}
int maxa(int a,int b)
{
return a>b? a:b;
}
int dp()
{
int max;
int **get=new int*[n];
for(int f=0;f<n;++f)
{
get[f]=new int[n];
}
get[0][n-1]=0;
for(int i=0;i<c_p;++i)
{
for(int j=n;j>=0;--j)
{
int temp1=0,temp2=0;
if(i-1>=0)
{
temp1=get[i-1][j];
}
if(j+1<n)
{
temp2=get[i][j+1];
}
get[i][j]=mar[i][j]+maxa(temp1,temp2);
}
}
max=get[0][0];
for(int h=1;h<c_p;++h)
{
if(get[h][0]>max)
{
max=get[h][0];
}
}
return max;
}
int main()
{
cin>>n;
while(n!=0)
{
col=new int[n];
pos=new int[n];
mar=new int*[n];
c_p=0;
for(int i=0;i<n;++i)
{
cin>>col[i];
bool flag=true;
for(int j=0;j<c_p;++j)
{
if(pos[j]==col[i])
{
flag=false;
break;
}
}
if(flag==true)
{
pos[c_p++]=col[i];
}
mar[i]=new int[n];
}
qsort(pos,c_p,sizeof(int),compar);
for(int k=0;k<n;++k)
{
for(int l=0;l<c_p;++l)
{
mar[l][k]=0;
if(pos[l]==col[k])
{
mar[l][k]=1;
}
}
}
cout<<dp()<<endl;
cin>>n;
}
return 0;
}
解题思路: 首先将问题抽象成模型,在这里就是一个矩阵表示的炮弹分布图. 有的炮弹一样高,有的炮弹不一样高.
所以,矩阵的高应该是不同的高度的数量,矩阵的长应该是炮弹的数量n.
这里用到了离散化数据的技巧,不能理所当然的将10000米的炮弹设置为矩阵10000高,这样太费空间了.
所以,必须将不同的高度作为一个点处理,将不同高度的点压缩到一个很小的矩形上,只描述它们之间的次序,而不描述它们的具体高度.
例如下图分布: 有5个炮弹, 高度是100,9999,20,100,700,离散化后的矩阵应该是形如这样的:
9999
700
100 100
20
所以矩阵只需要高4,长5,就足以表示炮弹之间的位置关系了.
我采用O(n2)的时间复杂度进行离散. 方法如下:
利用col[n]存储输入的每个炮弹的高度, 利用pos[n](如果高度有重复,则用不了n个)存储炮弹出现过的不重复高度,
例如: 5 100 9999 20 100 700, 那么输入数据结束时,col[5]={100,9999,20,100,700} ,pos[4]={100,9999,20,700}
,这个记录过程是在输入数据过程中完成的. 无非一个col记录所有炮弹的高度,一个pos记录有哪几种高度。
现在,需要生成上面炮弹分布图M了,依据的就是col,pos数组., 首先把pos按高度自小到大排序 , 从col[0]开始到col[4],对每个col,去pos里找它所在的位置,例如先找100所在高度,发现它是pos里第1矮的,那么就标记M[1][0]=1,表示这里有炮弹。 然后9999,发现它是pos里第3矮的,那么标记M[3][1]=1. 对于20则是 M[0][2]=1, 对于100,M[1][3]=1,对于700,M[2][4]=1
现在炮弹分布图生成了,除了标记1的,其他都标记0 ,现在我们就有了一个非常直观的0,1矩阵. 1表示有炮弹,0表示没炮弹.
现在用动态规划O(n2)就可以解决问题了,sum[i][j]表示从(i,j)打出的炮弹能打到的最多数量,最终要求的是max{sum[0 to 3][0]},就是我们想要的结果.
由于出发点(i,j)不同,那么它能打到的炮弹的路线也不同,所以要求max{}。另外,DP转移式为sum[i][j]=max{sum[i-1][j],sum[i][j+1]+M[i][j]}, M[i][j] 就是那个炮弹分布图, 表示当前格子有没有炮弹,有炮弹当然也要算上1个。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/qq120848369/archive/2010/05/19/5606737.aspx
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
struct comp
{
bool operator()(int& a, int& b)
{
return a>b;
}
};
int main(int argc, char **argv)
{
int nb;
cin>>nb;
for(int i=0; i<nb; ++i)
{
int edge, vert;
cin>>vert>>edge;
//顶点序列,其中每个顶点的vector的int代表连接的其他顶点
vector<vector<int> > vectorEdge;
for(int k=0; k<vert; ++k)
vectorEdge.push_back(vector<int>());
int p1,p2;
for(int j=0; j<edge; ++j)
{
cin>>p1>>p2;vectorEdge[p1].push_back(p2);
}
for(int j=0; j<vert; ++j)
sort(vectorEdge[j].begin(),vectorEdge[j].end());//排序,从小号到大号
//---------------------------
bool arr[100];//记录哪几个点已经输出过了
int vertArr[100] = {0};//记录下个要查找的顶点
int temp = 1;
for(int m=0; m<vert; ++m)
arr[m] = true;
cout<<"0 ";
for(int m=0; m<vert; ++m)
{
for(int n=0; n<vectorEdge[vertArr[m]].size();++n)
{
int index = (vectorEdge[vertArr[m]])[n];
if(arr[index])//如果这个顶点还未输出
{
cout<<index<<" ";
vertArr[temp++] = index;//因为下个顶点还可以
arr[index] = false;
}
}
}
cout<<endl;
}
return 0;
}